<$> 和 <*> 是如何发音的?

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 xes 的所有总和。

正如 Daniel Wagner 在问题下的评论,[x, 0] 可以调整为 [x | x /= 0] ++ [0],以提高效率。

当我自己朗读这些时,我不会发音;它们只是我脑海中的一个视觉符号。如果我必须大声说出来,我会说 <$> 是“eff-map”(如果有歧义,可能是“eff-mapped to”),<*> 是“app”(可能是“applied to”)如果有歧义),它们来自 Applicative 之前的名称 fmapap.

此外,我讨厌大声说 fmap。出于这个原因和其他原因,我可能会在心理上将其转换为

pure (+) <*> [x,0] <*> allSums xs

在我说之前,所以我只需要发音pure(<*>)。顺便说一句,我觉得这种风格并不常见有点令人惊讶;特别是当跨多行传播应用参数时,这更统一,因为

pure f
    <*> a
    <*> b
    <*> c

不需要特殊对待 a 行。