A previous question讨论了如何将Haskell表达式ap zip tail
的类型转换为\x -> zip x (tail x)
的类型。这很有启发性,但是那里的问题和答案都没有处理为什么前面的表达式给出与后一个表达式相同的结果,只是它们的类型是等价的。据我所知,它可能意味着\x -> zip x (tail (tail x))
。
我尝试阅读ap的文档但无处可去。 如何阅读 ap
如何理解ap zip tail
提供的结果与\x -> zip x (tail x)
相同?
答案 0 :(得分:7)
首先,看看source:
ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
-- Since many Applicative instances define (<*>) = ap, we
-- cannot define ap = (<*>)
你知道(从上一个问题)我们感兴趣的monad是(->) [a]
。由于我们从该评论中得知ap
与(<*>)
相同,接下来我们会看
instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
(<*>) zip tail x = zip x (tail x)
我们可以向右移动x
并获取zip <*> tail = \x -> zip x (tail x)
。
您也可以直接使用ap
和instance Monad (->) a
的定义,而无需查看<*>
,但这需要更多的努力。
就我所知,它可能意味着\ x - &gt; zip x(tail(tail x))代替。
此实际上只能来自此类型的m (a -> b) -> m a -> m b
(c -> (a -> b)) -> (c -> a) -> (c -> b)
类型,因此ap f1 f2
无法应用f2
两次:它的类型为c -> a
,f2 (f2 <anything>)
不会进行类型检查。
答案 1 :(得分:1)
this answer的第二部分解释了它。请注意<*>
与ap
相同,但作为中缀运算符,作为Applicative
的一部分而不是它的子类Monad
,因为只有Applicative
它需要它才能工作。