不在范围内:输入构造函数或类“-”(以及反转列表时的其他错误)

时间:2018-10-13 22:52:16

标签: haskell

我正在研究《七周之内的七种语言》一书,Haskell上线第一天的问题之一是“ 编写一个接受列表并反向返回相同列表的函数< / em>”。

我的第一个实施效果很好:

reverseList :: [a] -> [a]
reverseList [] = []
reverseList [x] = [x]
reverseList (h:t) = reverseList(t) ++ [h]

然后我想到了另一种方法,我试图将其实现为:

reverseList1 :: [a] -> [a]
reverseList1 [] = []
reverseList1 [x] = [x]
reverseList1 l = last(l) :: reverseList1(take(length(l)-1)(l))

(即-取最后一个元素,然后将颠倒的first-all-but-one元素添加到该元素)。但是,这在尝试加载文件时给了我一个错误(实际上是三个):

[1 of 1] Compiling Day1             ( day1.hs, interpreted )

day1.hs:35:49: error: Not in scope: type constructor or class ‘-’
   |
35 |   reverseList1 l = last(l) :: reverseList1(take(length(l)-1)(l))
   |                                                 ^^^^^^^^^^^

day1.hs:35:49: error:
    Illegal operator ‘-’ in type ‘length (l) - 1’
      Use TypeOperators to allow operators in types
   |
35 |   reverseList1 l = last(l) :: reverseList1(take(length(l)-1)(l))
   |                                                 ^^^^^^^^^^^

day1.hs:35:59: error:
    Illegal type: ‘1’ Perhaps you intended to use DataKinds
   |
35 |   reverseList1 l = last(l) :: reverseList1(take(length(l)-1)(l))
   |                                                           ^
Failed, no modules loaded.

搜索“不在范围内”错误提示我正在尝试使用尚未导入的内容-我不认为需要明确导入“减”,根据其他实验。

我不明白第二个错误(Use TypeOperators to allow operators in types)-我从here看到TypeOperators是我可以在ghci上设置的标志,但是我不尝试在类型中使用运算符-就我所知,length(l)-1take的自变量,而不是类型。

谷歌搜索“也许您打算使用DataTypes”使我想到here-我希望我的代码不会像该示例那样被撕裂,但是我可能同样毫无头绪!


根据上一个示例here,我还尝试了:

reverseList1 l = last(l) :: reverseList1(take(takeLength)(l))
  where takeLength = length(l)-1

(从“无法匹配类型'a'”开始出现(很长!)错误)和

reverseList1 l =
  let takeLength = length(l)-1 in
  in last(l) :: reverseList1(take(takeLength)(l))

哪个给了

day1.hs:40:5: error: parse error on input ‘in’
   |
40 |     in last(l) :: reverseList1(take(takeLength)(l))
   |     ^^
Failed, no modules loaded.

1 个答案:

答案 0 :(得分:3)

列表由:构成。 ::表示一种类型,因此Haskell尝试将其读取为一种类型,因此会出现错误。

更正后的代码是:

reverseList1 :: [a] -> [a]
reverseList1 [] = []
reverseList1 [x] = [x]
reverseList1 l = last l : reverseList1 (take (length l - 1) l)

请注意使代码更具可读性的括号!

在第二次尝试中,您两次写入in,解析器感到困惑。

更正后的代码是:

reverseList1 l =
  let takeLength = length l - 1
  in last l : reverseList1 (take takeLength) l

现在,该错误实际上很有趣。 TypeOperators扩展名是允许(毫不奇怪)在类型声明中使用中缀运算符的扩展名。

在这里,编译器注意到-看起来像是一个infix运算符,并且鉴于它的类型符号被推断您可能打算使用TypeOperators扩展名。当然,这里不是这样!

对于DataKinds,这是一个相当高级的扩展,允许您将数据(例如1"Hello"等)放入类型中。我不会在这里确切地使用它,但是编译器提到它的原因是您在类型签名中使用了1,该签名只能与DataKinds扩展名一起使用。 / p>