"(\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5 " 是如何工作的?
How does "(\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5 " really work?
在this example from Learn you a Haskell中,作者展示了如何为函数->r
声明一个Applicative
的实例
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
return 是一个函数 \x -> f x (g x (h x))
,我认为 (+3) <*> (*2) <*> (/2)
return是一个函数 \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)
执行 return 函数 \x -> x+3 (x*2 (x/2))
,它如何与 lambda 函数进行模式匹配 \x y z -> [x,y,z]
? (实际上,除了最基本的简单函数之外,我在理解 lambda 函数方面仍然遇到一些困难。)
那个表达式实际上是在左边用括号括起来的:
(\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]
我想你搞错了优先顺序。表达式
(\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]
.
在this example from Learn you a Haskell中,作者展示了如何为函数->r
Applicative
的实例
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
return 是一个函数\x -> f x (g x (h x))
,我认为(+3) <*> (*2) <*> (/2)
return是一个函数\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)
执行 return 函数\x -> x+3 (x*2 (x/2))
,它如何与 lambda 函数进行模式匹配\x y z -> [x,y,z]
? (实际上,除了最基本的简单函数之外,我在理解 lambda 函数方面仍然遇到一些困难。)
那个表达式实际上是在左边用括号括起来的:
(\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]
我想你搞错了优先顺序。表达式
(\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]
.