首页 > 解决方案 > 为什么这种语法不能正确编译?

问题描述

在这里对 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.

标签: haskell

解决方案


foldr和的类型foldl略有不同:

foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b

foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b

但是您将相同的功能传递f给两者。

如果将参数替换fflip 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

推荐阅读