Haskell ***异常:Prelude.head:空列表

时间:2016-09-04 13:46:28

标签: list haskell

这个函数是要找出列表A中有多少元素小于列表B中的最小元素

每次递归发生时,A的长度列表都会减少直到emepty。

然而......它只返回Exception:Prelude.head:空列表 甚至不是0 ..

为什么会这样?

compareSmall::[Card] -> [Card] -> Int
compareSmall [] _ = 0
compareSmall _ [] = 0
compareSmall (x:xs) (y:ys) =         
        if   rank  (head tnt1) < rank (head tnt2)   then         
            1 + compareSmall (tail tnt1) (tnt2)      
        else if  rank (head (tail tnt1)) == rank (head tnt2) then       
            0 + compareSmall (tail tnt1) (tnt2)       
        else 
            0 + compareSmall (tail tnt1) (tnt2)
                    where tnt1 = rankCard (x:xs)
                          tnt2 = rankCard (y:ys)

1 个答案:

答案 0 :(得分:1)

为什么

您的问题在于rankCard返回一个空列表,因此tnt1tnt2在某个时刻是[]。然后在执行head tnt1时收到错误,因为head是部分函数,​​并且会在空列表而不是Maybe上抛出异常。

调用else if rank (head (tail tnt1)) == rank (head tnt2) then发生了这种情况,特别是(head (tail tnt1))tnt1是包含1个元素的列表时发出错误。

修复它

似乎你不需要你的第二个if语句,因为你永远不会修改你的tnt2列表,因此通过让递归运行一次并且不会抛出任何错误,它将被捕获到最后的其他语句。你的代码可能只是

compareSmall :: [Card] -> [Card] -> Int
compareSmall [] _ = 0
compareSmall _ [] = 0
compareSmall a b  =
  if rank (head tnt1) < rank (head tnt2)   then
    1 + compareSmall (tail tnt1) b
  else
    0 + compareSmall (tail tnt1) b
  where
    tnt1 = rankCard a
    tnt2 = rankCard b

旁注:Haskell具有在模式匹配时保留整个列表的语法,所以你可以这样做

compareSmall a@(x:xs) b@(y:ys) =
  ...
  where
    tnt1 = rank a
    tnt2 = rank b

如果你需要那个。