Haskell:功能组合刚刚损坏了我的大脑

时间:2012-08-03 21:29:24

标签: haskell

如果

*Main> :t concatMap
concatMap :: (a -> [b]) -> [a] -> [b]

*Main> :t replicate
replicate :: Int -> a -> [a]

然后如何运作

*Main> :t concatMap . replicate
concatMap . replicate :: Int -> [b] -> [b]

下式给出:

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

我的意思是,我对函数组合的理解是replicate应该返回concatMap期望的任何参数,以便(.)能够工作。但事实并非如此。那捕获的是什么?

2 个答案:

答案 0 :(得分:19)

如果您在签名中添加括号然后将它们排成一行,它可能会帮助您查看正在发生的事情:

replicate :: Int -> (a -> [a])
concatMap ::        (a -> [b]) -> ([a] -> [b])

现在,如果我们统一replicateconcatMapb的输出应该与a的输入相符,这应该是相当明显的,在这种情况下,输出类型为作文是[b] -> [b]

答案 1 :(得分:9)

困难可能来自令人困惑的类型变量以及如何 你推理类型统一。诀窍是考虑,如 其他人说,( - >)是右关联的,这意味着你可以 像这样排队(为每个人制作新的类型变量 签名以避免混淆):

(.)       :: (b         ->  c         ) -> (a    -> b        )  -> a -> c
concatMap :: (q -> [r]) -> ([q] -> [r])
replicate ::                               (Int  -> (s -> [s])

这实质上为我们提供了一些我们需要解决的限制。 假设“a~b”表示“a与b的类型相同”或 等价地“a可以用b代替。”

从上面我们可以推断出以下事实:

a ~ Int
b ~ (q -> [r]) ~ (s -> [s])
c ~ ([q] -> [r])

但是b的两个等价物告诉我们

(q -> [r]) ~ (s -> [s])

需要

q ~ s and [r] ~ [s]

然后我们将c重写为:

c ~ ([q] -> [r]) ==> ([s] -> [s]))

将a和c的替换插入原始 应用了两个函数的(。)类型产生

a -> c ~ Int -> ([s] -> [s]) 

当然现在采用ghci报告的形式:Int -> [b] -> [b]