Haskell:怎么发音?

你如何发音这些函数在Applicativetypes:

(<*>) :: f (a -> b) -> fa -> fb (*>) :: fa -> fb -> fb (<*) :: fa -> fb -> fa 

(也就是说,如果他们不是经营者,他们会被称为什么?)

作为一个方面说明,如果你能把pure名字改名为对非math家更友善的话,你会怎样称呼它呢?

对不起,我真的不知道我的math,所以我很好奇如何发音在应用types的function

知道你的math,在我看来,这在很大程度上是无关紧要的。 正如你可能知道的那样,Haskell从抽象math的各个领域借鉴了一些术语,最着名的是类别理论 ,从中我们得到函子和单子。 这些术语在Haskell中的使用与正式的math定义有所分歧,但它们通常足够接近,无论如何都是很好的描述性术语。

Applicativetypes类位于FunctorMonad之间,所以人们会期望它具有类似的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上工作, notMaybe 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 。 烦!

另一方面,如果我们使用MaybeMonad实例,我们可以很容易地做到这一点:

 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的typesmfEmptyf ()

我们也不想强制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) 

这也向我们展示了pureMonoid的身份元素有关,所以其他的好名字可能是任何暗示单位值,空操作等的东西。


这是漫长的,所以总结一下:

  • (<*>)只是一个修改过的函数应用程序,所以你可以把它看作“ap”或“apply”,或者完全按照正常的函数应用程序的方式来读取它。
  • (<*>)也粗略地概括了列表上的zipWith ,所以你可以把它读作“zip functor with”,类似于把fmap读作“map a functor with”。

第一个更接近Applicativetypes类的意图 – 顾名思义 – 这就是我所推荐的。

事实上,我鼓励所有被解除的应用程序运营商自由使用,而不是发音

  • (<$>) ,它将单参数函数提升到Functor
  • (<*>) ,它通过Applicative来链接多参数函数
  • (=<<) ,它将进入Monad的函数绑定到现有的计算上

这三个核心都只是定期的function应用,一点点调味。

由于我没有改进CA McCann技术答案的雄心,我将解决更蓬松的问题:

如果你能把pure重命名为像我这样的小伙子更友善的话,你会怎样称呼它?

作为另一种select,特别是因为没有止境的对Monad版本的被称为“ return ”的持续的焦虑和背叛,我提出了另一个名字,它以一种能够满足最需要的命令式程序员,以及最实用的…好吧,希望每个人都可以抱怨: inject

拿一个价值。 “注入”到FunctorApplicativeMonad ,或者你有什么。 我投“ 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在这里有一个关于语言运算符发音的页面