函数组合运算符(。)和fmap(<$>)之间的区别

布伦丹

目前正在阅读这篇文章(顺便说一句非常出色),并且有一个非常简单的问题:

如果我将(+3)这样的两个函数结合(+2)在一起<$>,似乎会给我一个新函数,将传递的值加5。如果我对函数组合运算符执行相同的操作,即(+3) . (+2),会不会执行相同的操作?如果是这样,那么这两个运算符之间是否存在关系,以便在这种简单情况下它们可以执行相同的操作?

这甚至是一个明智的问题吗?

紧急命令

函数fmap<$>两者具有相同的类型:

> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b

虽然功能.

> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

那么我们怎么可能fmap在一个函数上使用并最终得到结果.呢?我假设您了解什么是函子,所以现在您必须了解“函数”是函子。怎么会这样?

> :i (->)
data (->) a b   -- Defined in `GHC.Prim'
instance Monad ((->) r) -- Defined in `GHC.Base'
instance Functor ((->) r) -- Defined in `GHC.Base'
instance Applicative ((->) a) -- Defined in `Control.Applicative'

Just[]不同Left函数没有可使用的构造函数。Functor实例将应用于语法本身。从ghci中的:info可以看到,语法箭头->实际上有一个functor的实例。

当我们看+3的类型时会发生什么?

> :t (+3)
(+3) :: Num a => a -> a

因此,函数(+3)是一个Functor,它接受a并返回a。当我们fmap在Functor上使用并且还给我们Functor时,我们得到嵌套的Functor:

> :t fmap Just (Just 3)
fmap Just (Just 3) :: Num a => Maybe (Maybe a)
> :t fmap (replicate 5) [1,2,3]
fmap (replicate 5) [1,2,3] :: Num a => [[a]]

同样,当我们将fmap两个函数应用于一个函数时,就会在一个函数内部得到一个函数。唯一的区别是它们融合在一起:

> :t (fmap (+3) (+2))
(fmap (+3) (+2)) :: Num a => a -> a

为什么这不会导致类型(->) (->) a a我们必须记住,的第一个参数fmap是函数(a -> b)而不一定是函子。因此,当我们这样做时,fmap g (Just 5)我们可以进行任何转换。但是,只要我们fmap对某个函数执行操作,我们就会知道它总是在函数内部产生。

因此fmap (+3) (+2)计算结果如下:\x -> (\x' -> x' + 3) (x + 2)那是一种真正的round回写作方式(+3) . (+2)

> :t (fmap (+3) (+2))
(fmap (+3) (+2)) :: Num a => a -> a
> :t ((.) (+3) (+2))
((.) (+3) (+2)) :: Num a => a -> a

通常,为了解决concat问题,(Maybe (Maybe a))或者[[a]]实际上我们需要依赖于a Monad a,以便可以使用bind >>=但是函数(->)是一种特殊情况,因为我们知道每次fmap在函数上使用时,它总是会在函数的一边为我们提供函数。除之外的任何其他Functor都不能说这一点->因此,我们可以确保始终将fmap功能串联在一起

因此任何 f <$> g == f . g

编辑:一个简短的注释,如果执行此操作,则fmap (+) (+0)最终会在函数内部产生一个函数。在这种情况下,>>=实际上需要monadic bind()来串联函数:

> :t fmap (+) (+0)
fmap (+) (+0) :: Num a => a -> a -> a
> :t (+0) >>= (+)
(+0) >>= (+) :: Num b => b -> b
> let bindfunc = (+0) >>= (+)
> bindfunc 5
10

这与我们所做的行为并不完全不同[1,2] >>= replicate 5

> [1,2] >>= replicate 5
[1,1,1,1,1,2,2,2,2,2]

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

运算符和方法之间的区别

来自分类Dev

<>和!=比较运算符之间的区别?

来自分类Dev

if语句和“?/:”运算符之间的区别

来自分类Dev

VHDL中的mod和rem运算符之间的区别?

来自分类Dev

条件运算符和if-else之间的区别:

来自分类Dev

Boost.Spirit:运算符“%=”和“ =”之间的区别

来自分类Dev

Python:+ =运算符和追加之间的区别

来自分类Dev

Java中前缀和后缀++运算符之间的区别

来自分类Dev

<< / >>运算符重载和输入/输出功能之间的区别

来自分类Dev

C和C ++之间关于“ ^ =”运算符的区别

来自分类Dev

使用.get()和->运算符之间有区别吗?

来自分类Dev

解引用运算符(*)char *和int *之间的区别

来自分类Dev

Unicode和ASCII运算符之间的区别

来自分类Dev

<>和Microsoft Access中的NOT运算符之间的区别?

来自分类Dev

点运算符和get方法之间的区别

来自分类Dev

小部件和运算符之间的区别-Fiware?

来自分类Dev

at() 和重载运算符 [ ] C++ 之间的区别

来自分类Dev

之间的区别。EL 中的运算符和 []

来自分类Dev

移动分配运算符和移动构造函数之间的区别?

来自分类Dev

-和-减法运算符号之间的区别

来自分类Dev

vhdl +运算符和+函数有什么区别?

来自分类Dev

从初始化构造函数创建的对象和Assign运算符之间有什么区别?

来自分类Dev

之间的区别 和|| 或&和&&

来自分类Dev

构造函数之间的区别

来自分类Dev

Javascript:==数字和内联函数之间的运算符

来自分类Dev

构造函数和转换运算符之间的重载解析

来自分类Dev

在数组和int之间使用运算符

来自分类Dev

/和/ **之间的区别

来自分类Dev

SQL =和IN之间的区别

Related 相关文章

热门标签

归档