2012-08-03 65 views
7

如果哈斯克尔:函数组合刚刚破坏我的大脑

*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期望的参数,以使(.)能够工作。但它不会是这种情况。那么有什么问题呢?

+0

你问为什么'a - > [a]'匹配a - > [b]'? – sepp2k 2012-08-03 21:32:54

+0

@ sepp2k nope,'a's和'b's部分非常清晰(我认为) – artemave 2012-08-03 22:31:29

+1

+1为史诗般的问题标题。脑损伤肯定是高级函数式编程的共同结果。 ;-) – MathematicalOrchid 2012-08-06 13:41:19

回答

19

它可以帮助你看到发生了什么事情,如果你加括号的签名,然后将它们排队:

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

现在,应该是相当明显的的replicate输出适合当的concatMap输入我们统一ba,在这种情况下,组合的输出类型是[b] -> [b]

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]