我正在进入 Haskell,发现“learn you a Haskell”这本书最有帮助。我到了 applicative functors 的部分.
我对书中出现的以下内容感到困惑:
(\x y z -> [x, y, z]) <$> (+3) <*> (*2) <*> (/2) $ 5
产生输出:
[8.0,10.0,2.5]
首先,我已经在 ghci 中证实了我对运算符优先级的怀疑,因此上述内容等同于以下丑陋的陈述:
(((\x y z -> [x,y,z]) <$> (+3)) <*> (*2) <*> (/2)) $ 5
因此,很明显发生的第一件事是
fmap
。调用(<$>)
中缀运算符。这是目前令我难以置信的核心。
fmap
的定义(这里显示为中缀 (<$>)
)是:(<$>) :: (Functor f) => (a -> b) -> f a -> f b
但在我正在努力解决的等式中,
(\x y z -> [x, y, z])
需要三个参数,而不仅仅是一个。那么(a -> b)
类型的第一个参数怎么可能?满意?我认为这可能与部分应用程序/柯里化(Currying)有关,但我无法弄清楚。我将不胜感激。希望我已经很好地提出了这个问题。
最佳答案
简单的回答:Haskell 中没有具有多个参数的函数!
您可能称之为“二元函数”的候选函数有两个:一个采用(单个!)元组的函数,以及 - 迄今为止在 Haskell 中普遍存在的 - 柯里化(Currying)函数。那些只接受一个参数,但结果又是一个函数。
因此,要弄清楚例如fmap (+)
是的,让我们写
type IntF = Int -> Int
-- (+) :: Int -> IntF
-- fmap :: ( a -> b ) -> f a -> f b
-- e.g.:: (Int->IntF) -> f Int->f IntF
在 GHCi 中自己测试:
Prelude> type IntF = Int -> Int
Prelude> let (#) = (+) :: Int -> IntF
Prelude> :t fmap (#)
fmap (#) :: Functor f => f Int -> f IntF
关于haskell - 应用仿函数 : why can fmap take a function with more than one argument?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21376085/