haskell - 不在范围内:类型构造函数或类“-”(以及反转列表时的其他错误)
问题描述
我正在阅读“七周内的七种语言”一书,Haskell 第一天的一个问题是“编写一个函数,该函数接受一个列表并反向返回相同的列表”。
我的第一个实现效果很好:
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
) - 我从这里看到这TypeOperators
是一个我可以设置的标志ghci
,但我并没有尝试在类型中使用运算符 -length(l)-1
是(据我所知)一个参数take
,而不是类型。
谷歌搜索“也许你打算使用 DataTypes”把我带到了这里——我希望我的代码不会像那个例子那样被撕裂,但我可能同样一无所知!
基于此处的最后一个示例,我还尝试了:
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.
解决方案
列表是用 构造的:
。::
表示一个类型,因此 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
扩展是一种允许(不出所料)在类型声明中使用中缀运算符的扩展。
在这里,编译器注意到它-
看起来像一个中缀运算符,并且鉴于它在类型签名中,推断您可能打算使用TypeOperators
扩展。当然,这里不是这样的!
至于DataKinds
,这是一个相当高级的扩展,允许您将数据(如1
等"Hello"
)放入类型中。我不会在这里详细介绍它的用途,但编译器提到它的原因是您1
在类型签名中使用了它,它只能与DataKinds
扩展一起使用。
推荐阅读
- pdf - 将图像添加到 Apache PDFBox 中的 PDPushButton
- python - 读取最大 4GB 的文件而不会出现 MemoryError
- javascript - Redux useReducer 和 mapDispatchToProps 不起作用
- java - 当相机应用程序打开以在 android studio 中获取图像时,您可以打开图库吗?
- javascript - 单击时的 HTML 图像对象不起作用
- python - 如何在 UT 执行中模拟 http 调用,并在 python 中返回实际流的实际响应
- angular - 如何在需要知道“主机名”的 Angular 应用程序上运行 Pagespeed?
- datetime - 需要从输入 xml 减少 20 天前
- varnish - 当通过我的 Varnish 服务器发出请求时,如何自定义向遇到 Guru Meditation 错误的用户显示的消息?
- sql-server - 在 SQL Server 中查找以下结果的查询