我是Haskell的初学者,我试图将列表分成两个大小相等的子列表。该模块可以加载,但是当我尝试运行ghci时,它不起作用 例如: divideList [1,2,3,4] = [1,2] [3,4] divideList [1,2,3,4,5] = [1,2,3] [4,5]
divideList [] = ([],[])
divideList [x] = ([x],[])
divideList ((x:xs):ys) = if a < b
then splitAt (a+1) ((x:xs):ys)
else divideList (xs:ys)
where a = length xs
b = length ys
它说“没有(Num [t0])的实例来自字面'2'”。我不知道如何解决它。谁能帮我???谢谢!
这是我在ghci中键入divideList [2,3,5]时指示的错误。
<interactive>:2:13:
No instance for (Num[a0]) arising from literal '2'
Possible fix: add an instance declaration for (Num[a0])
In the expression: 2
In the first argument of 'divideList', namely "[2,3,5]
In the expression: divideList [2,3,5]
答案 0 :(得分:6)
首先关闭:伙计,我的{格式,类型签名}在哪里?
第二:您所说的错误表明您在类型中表示值应该是列表的位置使用了数字文字(例如:1
)。因为解释文字是灵活的(多态),类型检查器会抱怨你需要告诉它如何将数字解释为列表。
第三:发布的代码(重新格式化并在下面提供类型签名)不会产生您声明的错误。
第四:发布的代码不执行您描述的任务 - 单独的类型签名是一个强烈的提示 - 您描述的函数应该将列表带到列表对([a] -> ([a],[a])
但是您定义了一个消耗列表的函数列表([[a]] -> ([[a]],[[a]])
)...
divideList :: [[a]] -> ([[a]], [[a]])
divideList [] = ([],[])
divideList [x] = ([x],[])
divideList ((x:xs):ys) =
if a < b
then splitAt (a+1) ((x:xs):ys)
else divideList (xs:ys)
where a = length xs
b = length ys
答案 1 :(得分:0)
正如托马斯所说,如果在编写实现之前写出类型签名,通常应该让您更好地了解您希望代码执行的操作。
如果我理解您的代码是正确的,那么您打算从提供的列表的左侧开始,并推进直到列表的左侧大于或等于右侧的大小那边,你把它分开了。
如果是这种情况,那么您的代码中会出现一些错误:
您当前的逻辑是&lt; b然后拆分,其中a =长度xs(假设左侧)和b =长度ys(假设右侧)。假设你从左边开始,左边将比右边小一些开始!所以在这种情况下,你应该有一个&gt; b而不是。
您对模式匹配的使用不正确 - (x:xs):ys表示“将列表的第一个元素作为(x:xs),这是单个元素x加上列表的其余部分xs ,其余为ys“。所以这种模式匹配试图将列表(2)的第一个元素转换为一个列表,这样它就可以从中提取(x:xs),这就是你的错误来源。
如果你希望将列表大致分成两半,我只会做更像
的事情mySplit list = splitAt ((length list) `div` 2) list
更简单:)