haskell - 为什么这种语法不能正确编译?
问题描述
在这里对 Haskell 来说非常陌生。我不确定为什么这种语法案例无法正确编译:
-- | Use column headers to determine offsets for each row in a table
splitHeader :: Alignment -> String -> [(String,Int)]
splitHeader a h = case a of
AlignLeft -> reverse ((foldr f b h) ("", 0) [] 2)
AlignRight -> reverse ((foldl f b h) ("", 0) [] 2)
where b (n', w') l' m' = (reverse n', w'):l'
f c b (n, w) l m
| m == 2 && c == ' ' = b (n, w+1) l 0
| m == 2 && c /= ' ' = b (c:n, w+1) l 1
| m == 1 && c == ' ' = b (n, w+1) l 0
| m == 1 && c /= ' ' = b (c:n, w+1) l 1
| m == 0 && c == ' ' = b (n, w+1) l 0
| m == 0 && c /= ' ' = b ([c], 1) ((reverse n, w):l) 1
编译错误:
Kata.hs:50:43: warning: [-Wdeferred-type-errors]
• Couldn't match type ‘([Char], Int)
-> [([Char], Int)] -> Integer -> [([Char], Int)]’
with ‘Char’
Expected type: (([Char], Int)
-> [([Char], Int)] -> Integer -> [([Char], Int)])
-> (([Char], Int) -> [([Char], Int)] -> Integer -> [([Char], Int)])
-> ([Char], Int)
-> [([Char], Int)]
-> Integer
-> [([Char], Int)]
Actual type: Char
-> (([Char], Int) -> [([Char], Int)] -> Integer -> [([Char], Int)])
-> ([Char], Int)
-> [([Char], Int)]
-> Integer
-> [([Char], Int)]
• In the first argument of ‘foldl’, namely ‘f’
In the first argument of ‘reverse’, namely
‘((foldl f b h) ("", 0) [] 2)’
In the expression: reverse ((foldl f b h) ("", 0) [] 2)
|
50 | AlignRight -> reverse ((foldl f b h) ("", 0) [] 2)
| ^
Kata.hs:50:47: warning: [-Wdeferred-type-errors]
• Couldn't match type ‘Char’
with ‘([Char], Int)
-> [([Char], Int)] -> Integer -> [([Char], Int)]’
Expected type: [([Char], Int)
-> [([Char], Int)] -> Integer -> [([Char], Int)]]
Actual type: String
• In the third argument of ‘foldl’, namely ‘h’
In the first argument of ‘reverse’, namely
‘((foldl f b h) ("", 0) [] 2)’
In the expression: reverse ((foldl f b h) ("", 0) [] 2)
|
50 | AlignRight -> reverse ((foldl f b h) ("", 0) [] 2)
| ^
Ok, one module loaded.
解决方案
foldr
和的类型foldl
略有不同:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
但是您将相同的功能传递f
给两者。
如果将参数替换f
为flip f
类型,则结果:
splitHeader :: Alignment -> String -> [(String,Int)]
splitHeader a h = case a of
AlignLeft -> reverse ((foldr f b h) ("", 0) [] 2)
AlignRight -> reverse ((foldl (flip f) b h) ("", 0) [] 2)
where b (n', w') l' m' = (reverse n', w'):l'
f c b (n, w) l m
| m == 2 && c == ' ' = b (n, w+1) l 0
| m == 2 && c /= ' ' = b (c:n, w+1) l 1
| m == 1 && c == ' ' = b (n, w+1) l 0
| m == 1 && c /= ' ' = b (c:n, w+1) l 1
| m == 0 && c == ' ' = b (n, w+1) l 0
| m == 0 && c /= ' ' = b ([c], 1) ((reverse n, w):l) 1