4

我是 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]
4

2 回答 2

6

First off: Dude, where's my {formatting, type signatures}?

Second: The error you are talking about indicates you have used a numeric literal (ex: 1) in a place where the types say the value should be a list. Because interpreting literals is flexible (polymorphic), the type checker complains that you need to tell it how to interpret a number as list.

Third: The posted code (reformatted and provided a type signature below) does not produce the error you claim.

Fourth: The posted code does not perform the task you describe - the type signature alone is a strong hint - the function you described should take lists to pairs of lists ([a] -> ([a],[a]) but you defined a function that consumes lists of lists ([[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
于 2013-09-30T05:28:17.487 回答
0

正如 Thomas 所说,如果您在编写实现之前写出类型签名,它通常应该让您更好地了解您希望您的代码做什么。

如果我对您的代码的理解是正确的,那么您打算从提供的列表的左侧开始,一直前进直到列表的左侧大于或等于右侧的大小,在哪一点你分裂它。

如果是这种情况,那么您的代码中有几个错误:

  1. 您当前的逻辑是如果 a < b 然后拆分,其中 a = 长度 xs (假设左侧)和 b = 长度 ys (假设右侧)。假设你从左边开始,左边会比右边小!因此,在这种情况下,您可能应该使用 a > b 代替。

  2. 您对模式匹配的使用不正确 - (x:xs):ys 的意思是“将列表的第一个元素作为 (x:xs),它是单个元素 x 加上列表 xs 的其余部分,然后其余作为 ys ”。因此,此模式匹配试图将列表 (2) 的第一个元素转换为列表,以便从中提取 (x:xs) ,这就是您的错误的来源。

如果您希望将列表大致分成两半,我只会做更多类似的事情

mySplit list = splitAt ((length list) `div` 2) list

这更简单:)

于 2013-09-30T10:23:07.690 回答