Haskell:怎么发音?
你如何发音这些函数在Applicativetypes:
(<*>) :: f (a -> b) -> fa -> fb (*>) :: fa -> fb -> fb (<*) :: fa -> fb -> fa
(也就是说,如果他们不是经营者,他们会被称为什么?)
作为一个方面说明,如果你能把pure
名字改名为对非math家更友善的话,你会怎样称呼它呢?
对不起,我真的不知道我的math,所以我很好奇如何发音在应用types的function
知道你的math,在我看来,这在很大程度上是无关紧要的。 正如你可能知道的那样,Haskell从抽象math的各个领域借鉴了一些术语,最着名的是类别理论 ,从中我们得到函子和单子。 这些术语在Haskell中的使用与正式的math定义有所分歧,但它们通常足够接近,无论如何都是很好的描述性术语。
Applicative
types类位于Functor
和Monad
之间,所以人们会期望它具有类似的math基础。 Control.Applicative
模块的文档开始于:
这个模块描述了函子和monad之间的中间结构:它提供纯粹的expression式和sorting,但没有绑定。 (从技术上讲,这是一个强大的monoidal函数。)
嗯。
class (Functor f) => StrongLaxMonoidalFunctor f where . . .
不像Monad
那么吸引人,我想。
基本上归结为Applicative
并不符合任何math上特别有趣的概念,所以没有现成的术语来描述它在Haskell中的使用方式。 所以,现在把math放在一边。
如果我们想知道要调用什么(<*>)
,可能有助于了解它的基本含义。
那么,无论如何, Applicative
有什么问题?为什么我们这样称呼?
实际上, Applicative
是一种将任意函数提升到Functor
。 考虑Maybe
(可以说是最简单的非平凡Functor
)和Bool
(同样是最简单的非平凡数据types)的组合。
maybeNot :: Maybe Bool -> Maybe Bool maybeNot = fmap not
函数fmap
可以让我们从Bool
上工作, not
在Maybe Bool
上工作。 但是如果我们要解除(&&)
呢?
maybeAnd' :: Maybe Bool -> Maybe (Bool -> Bool) maybeAnd' = fmap (&&)
那么,那不是我们想要的 ! 事实上,这是非常无用的。 我们可以试着聪明地把另一个Bool
潜入到Maybe
maybeAnd'' :: Maybe Bool -> Bool -> Maybe Bool maybeAnd'' xy = fmap ($ y) (fmap (&&) x)
…但这不好。 首先,这是错误的。 另一件事,这是丑陋的 。 我们可以继续尝试,但事实certificate, 没有办法提升多个参数的函数来处理一个任意的Functor
。 烦!
另一方面,如果我们使用Maybe
的Monad
实例,我们可以很容易地做到这一点:
maybeAnd :: Maybe Bool -> Maybe Bool -> Maybe Bool maybeAnd xy = do x' <- x y' <- y return (x' && y')
现在,翻译一个简单的函数liftM2
麻烦 – 这就是为什么Control.Monad
提供了一个函数来自动完成的, liftM2
。 这个名字中的2是指这样一个事实,即它在两个参数的函数上起作用。 对于3,4和5个参数函数存在类似的函数。 这些function比较好 ,但并不完美,指定参数的数量是丑陋的,笨拙的。
这引出了我们引入应用types类的论文 。 其中,作者基本上有两个观察:
- 将多参数函数提升到
Functor
是一件很自然的事情 - 这样做并不需要
Monad
的全部function
正常function应用是通过简单的并列术语来编写的,所以为了使“解除应用”尽可能简单自然,引入了中缀运算符来代替应用程序,将其提升到Functor
,并提供一个types类来提供所需的那。
所有这些都给我们带来了以下几点: (<*>)
只是简单地表示函数应用程序 – 那么为什么要发出不同于空白的“并列运算符”呢?
但是,如果这不是很令人满意,我们可以观察到, Control.Monad
模块还提供了一个function,为monad做同样的事情:
ap :: (Monad m) => m (a -> b) -> ma -> mb
ap
当然是“申请”的缩写。 由于任何Monad
都可以是Applicative
,并且ap
只需要后者中存在的特征的子集,所以我们可以说如果(<*>)
不是运算符,则它应该被称为ap
。
我们也可以从另一个方向来看事物。 Functor
提升操作称为fmap
因为它是对列表中的map
操作的一般化。 (<*>)
是什么样的function? 当然,列表上有什么是ap
的,但是这并不是特别有用。
实际上,列表可能有更自然的解释。 当你看到下面的types签名时想到什么?
listApply :: [a -> b] -> [a] -> [b]
对列表并行排列的想法有一些启发,将第一个函数应用到第二个函数的相应元素中。 不幸的是,对于我们的老朋友Monad
,这个简单的操作违反了单子法则,如果列表长度不同的话。 但它是一个很好的Applicative
,在这种情况下(<*>)
成为将zipWith
的通用版本串在一起的一种方式,所以我们可以想象将它fzipWith
?
这个压缩的想法实际上给我们带来了一个圆圈 回想一下math的东西,关于monoidal仿函数? 顾名思义,这是一种将monoids和functor结合在一起的方法,两者都是熟悉的Haskelltypes类:
class Functor f where fmap :: (a -> b) -> fa -> fb class Monoid a where mempty :: a mappend :: a -> a -> a
如果你把它们放在一个盒子里,把它们摇起来,它们会是什么样子? 从Functor
我们将保持独立于其types参数的结构的想法,并且从Monoid
我们将保持函数的整体forms:
class (Functor f) => MonoidalFunctor f where mfEmpty :: f ? mfAppend :: f ? -> f ? -> f ?
我们不想假设有一种方法可以创build一个真正的“空” Functor
,而且我们不能mfEmpty
任意types的值,所以我们将mfEmpty
的typesmfEmpty
为f ()
。
我们也不想强制mfAppend
需要一个一致的types参数,所以现在我们有这个:
class (Functor f) => MonoidalFunctor f where mfEmpty :: f () mfAppend :: fa -> fb -> f ?
mfAppend
的结果types是mfAppend
? 我们有两种我们一无所知的任意types,所以我们没有太多select。 最明智的是保持两个:
class (Functor f) => MonoidalFunctor f where mfEmpty :: f () mfAppend :: fa -> fb -> f (a, b)
在这一点上, mfAppend
现在显然是列表中的zip
一个普遍版本,我们可以轻松地重构Applicative
:
mfPure x = fmap (\() -> x) mfEmpty mfApply fx = fmap (\(f, x) -> fx) (mfAppend fx)
这也向我们展示了pure
与Monoid
的身份元素有关,所以其他的好名字可能是任何暗示单位值,空操作等的东西。
这是漫长的,所以总结一下:
-
(<*>)
只是一个修改过的函数应用程序,所以你可以把它看作“ap”或“apply”,或者完全按照正常的函数应用程序的方式来读取它。 -
(<*>)
也粗略地概括了列表上的zipWith
,所以你可以把它读作“zip functor with”,类似于把fmap
读作“map a functor with”。
第一个更接近Applicative
types类的意图 – 顾名思义 – 这就是我所推荐的。
事实上,我鼓励所有被解除的应用程序运营商自由使用,而不是发音 :
-
(<$>)
,它将单参数函数提升到Functor
-
(<*>)
,它通过Applicative
来链接多参数函数 -
(=<<)
,它将进入Monad
的函数绑定到现有的计算上
这三个核心都只是定期的function应用,一点点调味。
由于我没有改进CA McCann技术答案的雄心,我将解决更蓬松的问题:
如果你能把
pure
重命名为像我这样的小伙子更友善的话,你会怎样称呼它?
作为另一种select,特别是因为没有止境的对Monad
版本的被称为“ return
”的持续的焦虑和背叛,我提出了另一个名字,它以一种能够满足最需要的命令式程序员,以及最实用的…好吧,希望每个人都可以抱怨: inject
。
拿一个价值。 “注入”到Functor
, Applicative
, Monad
,或者你有什么。 我投“ inject
”,我批准了这个消息。
我一直喜欢wrap
。 拿一个价值,包装在一个Functor,Applicative,Monad中。 当在具有具体实例的句子中使用时,它也可以很好地工作: []
, Maybe
等。“它取值并包装在X
”。
(<*>) -- Tie Fighter (*>) -- Right Tie (<*) -- Left Tie pure -- also called "return"
资料来源:Chris Allen和Julie Moronuki的“Haskell Programming from First Principles”
简单来说:
-
你可以称它为“ 适用” 。 所以
Maybe f <*> Maybe a
可以发音为适用Maybe f
Maybe a
。 -
您可以将
pure
重命名of
,就像许多JavaScript库一样。 在JS中,你可以用Maybe.of(a)
创build一个Maybe
。
此外,Haskell的wiki在这里有一个关于语言运算符发音的页面