我目前正在阅读有关身份Monad的文章,其中一篇将fmap定义为:
fmap :: (a -> b) -> (W a -> W b)
fmap f (W x) = W (f x)
Run Code Online (Sandbox Code Playgroud)
文本说,目标是创建一个功能,将a和b类型的现有功能更改为将原始功能应用于Wa和w b的另一个功能。
从这个角度来看,涉及两个函数,类型签名也看起来像这样:它的参数是一个函数,并且提供了一个函数。
首先让我感到困惑的是,ghci告诉我们的fmap的实际类型是:
fmap :: (a -> b) -> W a -> W b
Run Code Online (Sandbox Code Playgroud)
对此进行的思考表明,函数fmap获取一个函数和类型为W a的参数,然后将该函数应用于Wa中的a上,并将结果返回为W b。恰好是fmap代码的功能描述。
我非常确定,如果在类型定义中省略了括号,那么函数的功能不会有任何区别。
我说对了,就像我会说的那样:
addab 是创建函数的函数,可以向其参数添加值
并给出以下示例代码:
addab :: Int -> (Int -> Int)
addab x y = x + y
add1 :: Int -> Int
add1 = addab 1
Run Code Online (Sandbox Code Playgroud)
基本上只是指示该函数是在没有提供所有参数的情况下使用的?
还是我没有考虑的更深层含义?
好吧,对于初学者来说,这没什么区别,因为它->是右关联的,其含义(a->b)->c->d定义为(a->b) -> (c->d)!
至于原因等等,您说的很对:这只是令人毛骨悚然。在Haskell中如此流行的一个特殊原因是,部分应用程序非常适合以一种自然的方式编写计算管道:之类的东西unzip . fmap f . reverse。在这里,fmap并不会真正接收其list参数,而只是接收应该传递给列表的态射。结果态射具有类型([a]->[b])。
(a->b) -> (F a->F d)实际上,这是更“基本的”定义:数学家将函子定义为将态射映射到射态。“功能和论据”的写作(a->b, F a) -> F b通常没有任何意义,因为在一般的类别中,没有有意义的方法可以将态射与对象相结合。正如诺曼所说,在笛卡尔封闭类别中,态射也是对象。