我知道点 (.) 运算符采用两个函数,这两个函数分别采用一个参数。
它的类型是
(.) :: (b -> c) -> (a -> b) -> a -> c
。
例如,
take 1 . drop 2 $ [1,2,3,4,5]
。
但是
(fmap . const)
如何发挥作用呢?
fmap 函数需要两个参数,const 函数接受两个参数,然后返回第一个参数。
因此从逻辑上讲,fmap 应该采用 const 函数采用的第一个参数的输出。
两个函数的类型:
fmap :: Functor f => (a -> b) -> f a -> f b
const :: a -> b -> a
(fmap . const) 2 (Just 4)
中的fmap应该得到const函数返回的输出2
,所以它不起作用,但实际上它确实有效。
发生什么事了?
只需统一类型即可:
fmap :: Functor f => (a -> b) -> (f a -> f b)
const :: b -> (a -> b)
fmap . const :: Functor f => b -> (f a -> f b)
所以
fmap . const
需要 x :: b
并产生 fmap (const x) :: f a -> f b
。
在你的例子中,
(fmap . const) 2 (Just 4)
= ((fmap . const) 2) (Just 4)
= fmap (const 2) (Just 4)
= Just (const 2 4)
= Just 4