在GHC和Haskell函数应用程序中调试类型错误

时间:2014-04-12 07:17:53

标签: haskell ghci

我在Haskell的99个问题中解决了10th问题。

我的解决方案是

-- Problem 10
encode:: String -> [(Int, Char)]
encode [] = []
encode (x:xs) = (length $ x : takeWhile (==x) xs, x) : encode $ dropWhile (==x) xs

我得到的错误是

Prelude> :l 10-20.hs 
[1 of 1] Compiling Main             ( 10-20.hs, interpreted )

10-20.hs:4:17:
    Couldn't match expected type `[Char] -> [(Int, Char)]'
                with actual type `[(Int, Char)]'
    The first argument of ($) takes one argument,
    but its type `[(Int, Char)]' has none
    In the expression:
      (length $ x : takeWhile (== x) xs, x) : encode
      $ dropWhile (== x) xs
    In an equation for `encode':
        encode (x : xs)
          = (length $ x : takeWhile (== x) xs, x) : encode
            $ dropWhile (== x) xs

10-20.hs:4:56:
    Couldn't match expected type `[(Int, Char)]'
                with actual type `String -> [(Int, Char)]'
    In the second argument of `(:)', namely `encode'
    In the expression: (length $ x : takeWhile (== x) xs, x) : encode
    In the expression:
      (length $ x : takeWhile (== x) xs, x) : encode
      $ dropWhile (== x) xs
Failed, modules loaded: none.

我将代码更改为

-- Problem 10
encode:: String -> [(Int, Char)]
encode [] = []
encode (x:xs) = (length $ x : takeWhile (==x) xs, x) : encode (dropWhile (==x) xs)

它编译并运行良好。请注意,我刚刚将encode $ dropWhile (==x) xs更改为encode (dropWhile (==x) xs)

我这里有两个问题

  • 如何从显示的GHCi错误中推断出我所做的更改(删除$应用程序)?我无法从抛出的错误中解读这个
  • 为什么要删除$

1 个答案:

答案 0 :(得分:3)

($)执行优先级非常低的函数应用程序,所以

(length $ x : takeWhile (==x) xs, x) : encode $ dropWhile (==x) xs

相当于

((length $ x : takeWhile (==x) xs, x) : encode) (dropWhile (==x) xs)

由于两个原因,这是错误的类型。首先,

((length $ x : takeWhile (==x) xs, x) : encode)

将是使用最外层(:)构建的列表,而不是函数,因此无法应用(因此关于“{1}}的第一个参数的第一个错误”应该采用一个参数)。其次,encode是一个($)函数,所以它不能是最外层String -> [(Int, Char)]的第二个参数(给定第一个参数的类型应该是(:),因此第二个错误)。