Cam*_*all 14 haskell types composition
我正试图在打"类型俄罗斯方块"方面做得更好.我有这些功能:
(=<<) :: Monad m => (a -> m b) -> m a -> m b
zip :: [a] -> [b] -> [(a, b)]
Run Code Online (Sandbox Code Playgroud)
而GHCi告诉我:
(zip =<<) :: ([b] -> [a]) -> [b] -> [(a, b)]
Run Code Online (Sandbox Code Playgroud)
我很难搞清楚如何从前两个签到最终签名.我的直觉(由于缺乏一个更好的词)是说的第一个参数=<<,即a -> mb以某种方式对和解的签名zip,然后将其都应该从脱落.但我无法理解如何实现这一飞跃.它可以分解为一系列易于遵循的步骤吗?
(zip =<<)相当于(>>= zip),这使得它可能更具可读性.无论哪种方式,正如您正确观察到的那样,zip占据了(a -> m b)这些功能中的插槽.
另一个更直观的转变是思考=<<.它"需要"两个参数,因此如果我们将它应用于一个参数,我们应该只剩下一个参数.因此,签名([b] -> [a]) -> [b] -> [(a, b)]是一元函数!
(zip =<<) :: ([b] -> [a]) -> ([b] -> [(a, b)])
------------ -----------------
m a' m b'
Run Code Online (Sandbox Code Playgroud)
那是什么m?Monad实例存在于函数(r ->)(或者,替代地(->) r).所以在这种情况下r :: [b](因而m :: ([b] ->)),a' :: [a]和b' :: [(a, b)].
因此,zip正如我们在开头所断言的那样:
a' -> m b' -- substitute [(a,b)] for b'
a' -> m [(a, b)] -- substitute [a] for a'
[a] -> m [(a, b)] -- substitute ([b] ->) for m
[a] -> ([b] -> [(a,b)])
[a] -> [b] -> [(a,b)]
Run Code Online (Sandbox Code Playgroud)
在其他事情之前做两件事有助于:
x->y->z变成了x->(y->z) 考虑到这一点,让我们重写类型
(=<<) :: Monad m => (a -> m b) -> (m a -> m b)
zip :: [x] -> ([y] -> [(x, y)])
Run Code Online (Sandbox Code Playgroud)
现在匹配类型.第一个参数=<<是zip,所以(a -> m b)是相同的[x] -> ([y] -> [(x, y)]).
a -> m b
[x] -> ([y] -> [(x, y)])
Run Code Online (Sandbox Code Playgroud)
所以,a是[x]和m b是([y] -> [(x, y)]).重写->前缀表示法,我们得到-> [y] [(x, y)],这是相同的(-> [y]) [(x, y)].
m b
(-> [y]) [(x, y)]
Run Code Online (Sandbox Code Playgroud)
那m是(-> [y])(确实是一个单子)而且b是[(x, y)].
所以现在我们知道什么是什么a,什么是b什么,什么是什么m.让我们(m a -> m b)用这些术语重写:
(m a) -> (m b)
((-> [y]) [x]) -> ((-> [y]) [(x, y)])
Run Code Online (Sandbox Code Playgroud)
我们再次以中缀风格重写
([y] -> [x]) -> ([y] -> [(x, y)])
Run Code Online (Sandbox Code Playgroud)
这就是变量名称,是GHC给你的答案.