Closed. This question is opinion-based。它当前不接受答案。
想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。
2年前关闭。
Improve this question
您如何在Applicative类型类中发音这些函数:
(也就是说,如果他们不是操作员,那么他们可能被称为什么?)
附带说明一下,如果您可以将
我认为不像
所有这些基本上可以归结为
如果我们想知道
那么
实际上,
函数
好吧,那根本不是我们想要的!实际上,这几乎没有用。我们可以尝试变得聪明,并通过背面将另一个
...但是那不好。一方面,这是错误的。另一方面,它很丑。我们可以继续尝试,但是事实证明,没有办法提升多个参数的功能来处理任意
另一方面,如果我们使用
现在,仅翻译一个简单的函数就很麻烦-这就是
这将我们带到paper that introduced the Applicative type class。在其中,作者基本上提出了两个观察:
将多参数函数提升为 这样做不需要
普通函数应用程序是用术语的简单并置编写的,因此,为了使“提升的应用程序”尽可能简单自然,本文引入了infix运算符来代表应用程序,并将其提升为
所有这些将我们带到以下几点:
但是,如果这还不能令人满意,我们可以观察到
当然
我们也可以从另一个方向着手。
实际上,列表可能有一种更自然的解释。当您查看以下类型签名时,会想到什么?
将列表并行排列的想法很吸引人,将第一个函数中的每个函数应用于第二个函数中的相应元素。不幸的是,对于我们的老 friend
这个压缩的想法实际上使我们充满了圈子。还记得以前关于单曲面函子的数学知识吗?顾名思义,这是组合类半体和函子的结构的一种方法,它们都是熟悉的Haskell类型类:
如果将它们放在一个盒子中并摇晃一下,它们会是什么样?从
我们不想假设有一种方法可以创建一个真正的“空”
我们也不想强迫
现在,
这也向我们显示
那很长,所以总结一下:
第一个更接近
实际上,我鼓励所有解除的应用程序操作员自由使用并禁止其发音:
从本质上讲,这三者只是常规功能的应用,而略微增加了一点。
想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。
2年前关闭。
Improve this question
您如何在Applicative类型类中发音这些函数:
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
(也就是说,如果他们不是操作员,那么他们可能被称为什么?)
附带说明一下,如果您可以将
pure
重命名为对非数学家更友好的名称,您会怎么称呼它? 最佳答案
抱歉,我不是很了解我的数学知识,所以我很好奇如何在Applicative类型类中发音这些函数
我认为,是否了解您的数学与这里无关。您可能已经知道,Haskell从抽象数学的各个领域借用了一些术语,最著名的是Category Theory,从中我们得到了函子和单子(monad)。在Haskell中,这些术语的使用与正式的数学定义有所不同,但它们通常足够接近,无论如何都是好的描述性术语。Applicative
类型类位于Functor
和Monad
之间,因此人们希望它具有相似的数学基础。 Control.Applicative
模块的文档开始于:
该模块描述了函子和monad之间的中间结构:它提供纯表达和排序,但不提供绑定(bind)。 (从技术上讲,是一个很松散的单曲面函子。)
嗯
class (Functor f) => StrongLaxMonoidalFunctor f where
. . .
我认为不像
Monad
那样吸引人。所有这些基本上可以归结为
Applicative
不对应任何在数学上特别有趣的概念,因此周围没有现成的术语可以捕捉到它在Haskell中的使用方式。因此,暂时搁置数学。如果我们想知道
(<*>)
的名称,可能会有助于了解它的基本含义。那么
Applicative
到底是怎么回事,为什么我们这样称呼它?实际上,
Applicative
相当于将任意函数提升为Functor
的方法。考虑Maybe
(可以说是最简单的非平凡Functor
)和Bool
(同样是最简单的非平凡数据类型)的组合。maybeNot :: Maybe Bool -> Maybe Bool
maybeNot = fmap not
函数
fmap
可让我们将not
从处理Bool
提升为处理Maybe Bool
。但是,如果我们要提升(&&)
怎么办?maybeAnd' :: Maybe Bool -> Maybe (Bool -> Bool)
maybeAnd' = fmap (&&)
好吧,那根本不是我们想要的!实际上,这几乎没有用。我们可以尝试变得聪明,并通过背面将另一个
Bool
潜入Maybe
中...maybeAnd'' :: Maybe Bool -> Bool -> Maybe Bool
maybeAnd'' x y = fmap ($ y) (fmap (&&) x)
...但是那不好。一方面,这是错误的。另一方面,它很丑。我们可以继续尝试,但是事实证明,没有办法提升多个参数的功能来处理任意
Functor
。烦人!另一方面,如果我们使用
Maybe
的Monad
实例,则可以轻松实现:maybeAnd :: Maybe Bool -> Maybe Bool -> Maybe Bool
maybeAnd x y = do x' <- x
y' <- y
return (x' && y')
现在,仅翻译一个简单的函数就很麻烦-这就是
Control.Monad
提供自动执行此功能的函数liftM2
的原因。名称中的2指的是它对正好两个参数的函数起作用; 3、4和5参数函数也存在类似的功能。这些函数是更好的,但不是完美的,并且指定参数的数量是丑陋且笨拙的。这将我们带到paper that introduced the Applicative type class。在其中,作者基本上提出了两个观察:
Functor
是很自然的事情Monad
的全部功能普通函数应用程序是用术语的简单并置编写的,因此,为了使“提升的应用程序”尽可能简单自然,本文引入了infix运算符来代表应用程序,并将其提升为
Functor
,并提供一个类型类来提供那。所有这些将我们带到以下几点:
(<*>)
仅仅表示函数应用程序-那么,为什么在发音上与在空白处“并置运算符”不同? 但是,如果这还不能令人满意,我们可以观察到
Control.Monad
模块还提供了对monad执行相同操作的函数:ap :: (Monad m) => m (a -> b) -> m a -> m b
当然
ap
是“apply”的缩写。由于任何Monad
都可以是Applicative
,并且ap
仅需要后者中存在的功能子集,因此我们可以说(如果(<*>)
不是运算符),则应将其称为ap
。 我们也可以从另一个方向着手。
Functor
提升操作称为fmap
,因为它是列表上map
操作的概括。列表上的哪种功能可以像(<*>)
一样工作?当然,ap
在列表上做了什么,但是它本身并不是特别有用。实际上,列表可能有一种更自然的解释。当您查看以下类型签名时,会想到什么?
listApply :: [a -> b] -> [a] -> [b]
将列表并行排列的想法很吸引人,将第一个函数中的每个函数应用于第二个函数中的相应元素。不幸的是,对于我们的老 friend
Monad
,如果列表长度不同,此简单操作将违反monad法则。但这是一个很好的Applicative
,在这种情况下(<*>)
成为将zipWith
的广义版本串在一起的一种方式,所以也许我们可以想象将其称为fzipWith
吗? 这个压缩的想法实际上使我们充满了圈子。还记得以前关于单曲面函子的数学知识吗?顾名思义,这是组合类半体和函子的结构的一种方法,它们都是熟悉的Haskell类型类:
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Monoid a where
mempty :: a
mappend :: a -> a -> a
如果将它们放在一个盒子中并摇晃一下,它们会是什么样?从
Functor
出发,我们将使结构的思想与其类型参数无关,从Monoid
出发,我们将保持函数的整体形式:class (Functor f) => MonoidalFunctor f where
mfEmpty :: f ?
mfAppend :: f ? -> f ? -> f ?
我们不想假设有一种方法可以创建一个真正的“空”
Functor
,并且我们不能想出一个任意类型的值,因此我们将mfEmpty
的类型固定为f ()
。我们也不想强迫
mfAppend
需要一个一致的类型参数,所以现在有了这个:class (Functor f) => MonoidalFunctor f where
mfEmpty :: f ()
mfAppend :: f a -> f b -> f ?
mfAppend
的结果类型是什么?我们有两个任意类型,我们一无所知,因此我们没有太多选择。最明智的做法是同时保留两个:class (Functor f) => MonoidalFunctor f where
mfEmpty :: f ()
mfAppend :: f a -> f b -> f (a, b)
现在,
mfAppend
现在显然是列表中zip
的广义版本,我们可以轻松地重建Applicative
:mfPure x = fmap (\() -> x) mfEmpty
mfApply f x = fmap (\(f, x) -> f x) (mfAppend f x)
这也向我们显示
pure
与Monoid
的identity元素相关,因此它的其他好名字可能是暗示单位值,空操作等的任何名称。那很长,所以总结一下:
(<*>)
只是一个经过修改的函数应用程序,因此您可以将其读取为“ap”或“apply”,也可以像正常函数应用程序一样完全删除它。 (<*>)
也大致概括了列表中的zipWith
,因此您可以将其读为“zip函子与”,类似于将fmap
读为“映射函子与”。 第一个更接近
Applicative
类型类的意图-顾名思义-因此,我建议这样做。实际上,我鼓励所有解除的应用程序操作员自由使用并禁止其发音:
(<$>)
,它将单参数函数提升为Functor
(<*>)
,它通过Applicative
链接多参数函数(=<<)
,它将将Monad
输入的函数绑定(bind)到现有的计算从本质上讲,这三者只是常规功能的应用,而略微增加了一点。
关于haskell - Haskell:<*>的发音是什么? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30799228/
10-13 03:09