<$> 和 <*> 是如何发音的?
How are <$> and <*> pronounced?
我正在学习Haskell。我被要求做的一个练习是计算一组整数的幂集的所有和,例如:
allSums [1, 2, 5] -- should be [8,3,6,1,7,2,5,0]
我在阅读了列表所属的应用程序和函子后想到了这个。成功了。
allSums :: [Int] -> [Int]
allSums [] = [0]
allSums (x:xs) =
if x == 0
then allSums xs
else (+) <$> [x, 0] <*> allSums xs
我被震撼了。它看起来很简洁,但看起来很正确。
我不知道该跟谁说。我的朋友和 parents 认为我疯了。
<$>
和 <*>
怎么发音?你甚至如何向人们描述他们所做的事情?
你将 <$>
和 <*>
的组合发音为 liftA2
:
liftA2 :: Applicative f
=> (a -> b -> c) -> f a -> f b -> f c
那么在你的情况下 f ~ []
、(+) :: Num a => a -> a -> a
和
liftA2 :: Num a
=> (a->a->a) -> [a] -> [a] -> [a]
-- (+) ...
(+) <$> [x,0] <*> allSums xs
=
[(x +), (0 +)] <*> allSums xs
=
liftA2 (+) [x,0] (allSums xs)
=
[x + r | x <- [x,0], r <- allSums xs]
在列表的情况下,它们“做”的是形成成分的类似笛卡尔积的组合,并将该函数应用于每个组合。
在对元素求和的情况下,对元素使用 0
就像完全跳过它一样。因此确实实现了数字的幂集的总和:
allSums [x1, x2, ..., xn]
=
[x1 + r | x1 <- [x1,0], r <- allSums [x2, ..., xn]]
=
[x1 + r | x1 <- [x1,0], r <- [x2 + r | x2 <- [x2,0], r <- allSums [x3, ..., xn]]]
=
[x1 + x2 + r | x1 <- [x1,0], x2 <- [x2,0], r <- allSums [x3, ..., xn]]
=
...
=
[x1 + x2 + ... + xn + r | x1 <- [x1,0], x2 <- [x2,0], ..., xn <- [xn,0], r <- [0]]
=
[x1 + x2 + ... + xn | x1 <- [x1,0], x2 <- [x2,0], ..., xn <- [xn,0]]
关于发音,我读(+) <$> [x, 0] <*> allSums xs
是“plus over x
-and-0 over x
es 的所有总和。
正如 Daniel Wagner 在问题下的评论,[x, 0]
可以调整为 [x | x /= 0] ++ [0]
,以提高效率。
当我自己朗读这些时,我不会发音;它们只是我脑海中的一个视觉符号。如果我必须大声说出来,我会说 <$>
是“eff-map”(如果有歧义,可能是“eff-mapped to”),<*>
是“app”(可能是“applied to”)如果有歧义),它们来自 Applicative
之前的名称 fmap
和 ap
.
此外,我讨厌大声说 fmap
。出于这个原因和其他原因,我可能会在心理上将其转换为
pure (+) <*> [x,0] <*> allSums xs
在我说之前,所以我只需要发音pure
和(<*>)
。顺便说一句,我觉得这种风格并不常见有点令人惊讶;特别是当跨多行传播应用参数时,这更统一,因为
pure f
<*> a
<*> b
<*> c
不需要特殊对待 a
行。
我正在学习Haskell。我被要求做的一个练习是计算一组整数的幂集的所有和,例如:
allSums [1, 2, 5] -- should be [8,3,6,1,7,2,5,0]
我在阅读了列表所属的应用程序和函子后想到了这个。成功了。
allSums :: [Int] -> [Int]
allSums [] = [0]
allSums (x:xs) =
if x == 0
then allSums xs
else (+) <$> [x, 0] <*> allSums xs
我被震撼了。它看起来很简洁,但看起来很正确。
我不知道该跟谁说。我的朋友和 parents 认为我疯了。
<$>
和 <*>
怎么发音?你甚至如何向人们描述他们所做的事情?
你将 <$>
和 <*>
的组合发音为 liftA2
:
liftA2 :: Applicative f
=> (a -> b -> c) -> f a -> f b -> f c
那么在你的情况下 f ~ []
、(+) :: Num a => a -> a -> a
和
liftA2 :: Num a
=> (a->a->a) -> [a] -> [a] -> [a]
-- (+) ...
(+) <$> [x,0] <*> allSums xs
=
[(x +), (0 +)] <*> allSums xs
=
liftA2 (+) [x,0] (allSums xs)
=
[x + r | x <- [x,0], r <- allSums xs]
在列表的情况下,它们“做”的是形成成分的类似笛卡尔积的组合,并将该函数应用于每个组合。
在对元素求和的情况下,对元素使用 0
就像完全跳过它一样。因此确实实现了数字的幂集的总和:
allSums [x1, x2, ..., xn]
=
[x1 + r | x1 <- [x1,0], r <- allSums [x2, ..., xn]]
=
[x1 + r | x1 <- [x1,0], r <- [x2 + r | x2 <- [x2,0], r <- allSums [x3, ..., xn]]]
=
[x1 + x2 + r | x1 <- [x1,0], x2 <- [x2,0], r <- allSums [x3, ..., xn]]
=
...
=
[x1 + x2 + ... + xn + r | x1 <- [x1,0], x2 <- [x2,0], ..., xn <- [xn,0], r <- [0]]
=
[x1 + x2 + ... + xn | x1 <- [x1,0], x2 <- [x2,0], ..., xn <- [xn,0]]
关于发音,我读(+) <$> [x, 0] <*> allSums xs
是“plus over x
-and-0 over x
es 的所有总和。
正如 Daniel Wagner 在问题下的评论,[x, 0]
可以调整为 [x | x /= 0] ++ [0]
,以提高效率。
当我自己朗读这些时,我不会发音;它们只是我脑海中的一个视觉符号。如果我必须大声说出来,我会说 <$>
是“eff-map”(如果有歧义,可能是“eff-mapped to”),<*>
是“app”(可能是“applied to”)如果有歧义),它们来自 Applicative
之前的名称 fmap
和 ap
.
此外,我讨厌大声说 fmap
。出于这个原因和其他原因,我可能会在心理上将其转换为
pure (+) <*> [x,0] <*> allSums xs
在我说之前,所以我只需要发音pure
和(<*>)
。顺便说一句,我觉得这种风格并不常见有点令人惊讶;特别是当跨多行传播应用参数时,这更统一,因为
pure f
<*> a
<*> b
<*> c
不需要特殊对待 a
行。