我目前正在阅读有关Monad身份的文章,其中一篇文章将fmap定义为:
fmap :: (a -> b) -> (W a -> W b)
fmap f (W x) = W (f x)
文本说目标是创建一个函数,将a和b类型的现有函数更改为将原始函数应用于W a和W b类型的另一个函数。
从这个角度来看,涉及两个函数,类型签名也如下所示:它的参数是一个函数,它提供了一个函数。
起初让我感到困惑的是,ghci的实际fmap类型是:
fmap :: (a -> b) -> W a -> W b
考虑到这一点,我们发现函数fmap得到一个函数和一个类型为W a的参数,然后将函数应用于W a中的a并将结果返回为W b。这恰好是对fmap代码的描述。
我很确定如果省略类型定义中的括号,它对函数的作用没有任何影响。
我是对的,这就像我会说的那样:
addab
是一个函数,它创建一个可以为其参数
并提供此示例代码:
addab :: Int -> (Int -> Int)
addab x y = x + y
add1 :: Int -> Int
add1 = addab 1
基本上只是指示在没有给出所有参数的情况下使用该函数?
或者有没有更深层的含义,我没有考虑过?
答案 0 :(得分:5)
嗯,对于初学者来说,无法有所作为,因为->
是右关联的,这意味着(a->b)->c->d
定义为(a->b) -> (c->d)
!< / p>
至于为什么等等,你是完全正确的:它只是在讨好。在Haskell中如此受欢迎的特殊原因是部分应用程序非常适合以自然的方式编写计算流水线:像unzip . fmap f . reverse
这样的东西。在这里,fmap
并没有真正收到它的列表参数,只有它应该提升到列表上的态射。结果态射的类型为([a]->[b])
。
这(a->b) -> (F a->F d)
实际上是更多&#34;基础&#34;定义:数学家将一个函子定义为将态射映射到态射; &#34;函数和参数&#34;写作(a->b, F a) -> F b
通常没有任何意义,因为在一般类别中,将态射与对象结合起来没有任何意义。只有,作为nomen sais,在笛卡尔封闭类别中态射也是对象。
答案 1 :(得分:4)
fmap
的这两种类型都是正确的。它们实际上是等价的。
你的实验也是正确的。
这里发生的是功能空间是一个封闭的笛卡尔类别。特别是,这意味着我们可以做部分功能应用。它很深,只要有逻辑/语言,其中部分功能应用程序作为推理规则是无效的。当然,这意味着Haskell比其他语言有更多有效的方法来计算程序。
例如,您自己定义的addab
函数和multab
函数让我们执行以下操作:
addab 1 . addab 2 . multab 3 $ 5