将构图应用于fmap

mac*_*688 3 haskell types composition

几周以来,我一直试图弄清楚Haskell编译器如何将(.)应用于fmap.

我的意思是.

:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

:t fmap
fmap :: Functor f => (a -> b) -> f a -> f b

:t (.) fmap
(.) fmap :: Functor f => (a -> a1 -> b) -> a -> f a1 -> f b
Run Code Online (Sandbox Code Playgroud)

编译器是如何得到(.)fmap的类型的?

我实际上是在这里问这个问题但是当我解释我尝试过的时候,所有这些都在一起.所以现在我也要发布答案了.

mac*_*688 5

为了得到这个,我拿了fmap

fmap :: Functor f => (a -> b) -> f a -> f b
fmap :: Functor f => (a -> b) -> (f a -> f b)
Run Code Online (Sandbox Code Playgroud)

如果

:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
Run Code Online (Sandbox Code Playgroud)

然后

(b - > c)(.)函数的开头可以替换为

((a -> b) -> (f a -> f b))
Run Code Online (Sandbox Code Playgroud)

因此,我有

((a1 -> b) -> (f a1 -> f b)) -> (a -> (a1 -> b)) -> a -> (f a1 -> f b)
Run Code Online (Sandbox Code Playgroud)

由于(.)已经应用于fmap,我们可以消除((a1 - > b) - >(f a1 - > fb))我们留下了

(a -> (a1 -> b)) -> a -> (f a1 -> f b)
Run Code Online (Sandbox Code Playgroud)

然后要额外清洁我们可以消除额外的括号.

来自IRC Beginner-haskell频道的Glguy和Hamme都提醒我( - >)是正确的联想

例如(a - > b - > c - > d)=(a - >(b - >(c - > d)))

所以我们消除了多余的括号.

(a -> a1 -> b) -> a -> f a1 -> f b

:t (.) fmap
(.) fmap :: Functor f => (a -> a1 -> b) -> a -> f a1 -> f b
Run Code Online (Sandbox Code Playgroud)