在玩了一下haskell后,我偶然发现了这个功能:
Prelude Data.Maclaurin> :t ((+) . ($) . (+))
((+) . ($) . (+)) :: (Num a) => a -> (a -> a) -> a -> a
(Data.Maclaurin由包向量空间导出。)因此它需要一个Num,一个函数,另一个Num并最终返回一个Num。下面的工作有什么神奇之处?
Prelude Data.Maclaurin> ((+) . ($) . (+)) 1 2 3
6
2显然不是一个功能(a-> a)或者我错过了什么?
答案 0 :(得分:16)
返回数字的函数的同一个包Data.NumInstances
和Num
实例的defines模块:
instance Num b => Num (a->b) where
(+) = liftA2 (+)
(*) = liftA2 (*)
fromInteger = pure . fromInteger
...
在Haskell中,像2
这样的整数文字是通用的,因此它可以代表Num
的任何实例的数字:
Prelude> :t 2
2 :: (Num t) => t
要将其转换为特定上下文中所需类型的实际数量,将调用fromInteger
类中的Num
。
由于上面提到的辅助模块为函数定义了Num
的实例,现在可以将 2
转换为函数,并在其中指定fromInteger
方法。
所以ghci调用fromInteger 2
来获取所需的函数作为问题中构造的第二个参数。然后整个表达式恰好评估为6
。
答案 1 :(得分:1)
你有充分的理由感到困惑。使用GHC中的Data.NumInstances
模块(由Data.Maclaurin
加载),可以将Num
强制转换为常量函数。
Prelude Data.NumInstances> :t (2 :: (Num a) => a -> a)
(2 :: (Num a) => a -> a) :: (Num a) => a -> a
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 0
2
Prelude Data.NumInstances> (2 :: (Num a) => a -> a) 1000
2
表达式的评估基本上是
((+) . ($) . (+)) 1 2 3 = ((+) . ($) . (1+)) 2 3
= ((+) (1+)) 2 3
-- (+) is defined for functions that return a Num
= ((+) (1+) (\_ -> 2)) 3
= ((+2) . (1+)) 3
= 6