在this example from Learn you a Haskell中,作者展示了如何为函数Applicative
声明->r
的实例
instance Applicative ((->) r) where
pure x = (\_ -> x)
f <*> g = \x -> f x (g x)
后来,他举了一个具体的例子
ghci> (\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5
[8.0,10.0,2.5]
我尝试逐步解释此片段
(+3) <*> (*2) <*> (/2)
视为f <*> g <*> h
并认为f <*> g <*> h
返回了函数\x -> f x (g x (h x))
,我认为(+3) <*> (*2) <*> (/2)
返回了函数\x -> x+3 (x*2 (x/2))
。但是我无法在ghci中使用:t (+3) <*> (*2) <*> (/2)
,这会引发此错误error:
• Occurs check: cannot construct the infinite type:
a1 ~ a -> a1 -> b
Expected type: (a -> a1 -> b) -> a1
Actual type: a1 -> a1
• In the second argument of ‘(<*>)’, namely ‘(/ 2)’
In the expression: (+ 3) <*> (* 2) <*> (/ 2)
(+3) <*> (*2) <*> (/2)
返回了函数\x -> x+3 (x*2 (x/2))
,它如何与lambda函数\x y z -> [x,y,z]
进行模式匹配? (实际上,除了真正简单的基本功能之外,我在理解lambda函数方面仍然遇到一些麻烦。)答案 0 :(得分:7)
我认为您弄错了优先顺序。表达式
(\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5
不不包含您提到的那个子表达式
(+3) <*> (*2) <*> (/2)
因为应该将其解析为与左侧关联,如下所示:
((((\x y z -> [x,y,z]) <$> (+3)) <*> (*2)) <*> (/2)) $ 5
在这里,我们从左边开始简化:
(\x y z -> [x,y,z]) <$> (+3)
= { def. <$> }
(\a y z -> [(+3) a,y,z])
然后,我们继续:
(\a y z -> [(+3) a,y,z]) <*> (*2)
= { def. <*> }
(\a z -> [(+3) a, (*2) a,z])
最后,
(\a z -> [(+3) a, (*2) a,z]) <*> (/2)
= { def. <*> }
(\a -> [(+3) a, (*2) a, (/2) a])
最后一步,我们将a
设为5
,得到[5+3, 5*2, 5/2]
。
答案 1 :(得分:4)
该表达式实际上被括在左侧:
(\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5
=
((((\x y z -> [x,y,z]) <$> (+3)) <*> (*2)) <*> (/2)) 5
=
((((\x y z -> [x,y,z]) . (+3)) <*> (*2)) <*> (/2)) 5
=
(((\x y z -> [x,y,z]) . (+3)) <*> (*2)) 5 ((/2) 5)
=
((\x y z -> [x,y,z]) . (+3)) 5 ((*2) 5) ((/2) 5)
=
(\x y z -> [x,y,z]) ((+3) 5) ((*2) 5) ((/2) 5)
=
(\x y z -> [x,y,z]) (5+3) (5*2) (5/2)
是
=
let x = (5+3) in (\y z -> [x,y,z]) (5*2) (5/2)
=
let x = (5+3) ; y = (5*2) in (\z -> [x,y,z]) (5/2)
=
let x = (5+3) ; y = (5*2) ; z = (5/2) in [x,y,z]