Haskell - 如何计算嵌套列表中的元素

时间:2015-07-05 21:27:19

标签: list haskell overloading counting

假设我已经嵌套了lsit:[1,[2,3,4],[5,[6]]]并且我想计算它有多少元素。在这种情况下,它是六个元素。我写了这样的代码:

totalElems :: [a] -> Int
totalElems (x:xs) = case (x, xs) of
                    (_, []) -> 0
                    (y:ys, _) -> 1 + totalElems ys + totalElems xs
                    (_, _) -> 1 + totalElems xs

但我有一个错误:

a.hs:4:42:
    Couldn't match expected type ‘a’ with actual type ‘[a0]’
      ‘a’ is a rigid type variable bound by
          the type signature for totalElems :: [a] -> Int at a.hs:1:15
    Relevant bindings include
      xs :: [a] (bound at a.hs:2:15)
      x :: a (bound at a.hs:2:13)
      totalElems :: [a] -> Int (bound at a.hs:2:1)
    In the pattern: y : ys
    In the pattern: (y : ys, _)
    In a case alternative:
        (y : ys, _) -> 1 + totalElems ys + totalElems xs

我如何在Haskell中做到这一点?

3 个答案:

答案 0 :(得分:7)

你不能像Haskell那样在列表中制作自由形式列表。动态类型的语言会像这样容忍愚蠢,但强类型的Haskell不会。

1的类型为Int,而[2,3,4]的类型为[Int]。列表中的内容必须属于同一类型。

但是,你可以这样做:

data Nest a = Elem a | List [Nest a]

example ::Nest Int
example = List [Elem 1, List [Elem 2, Elem 3, Elem 4], List [Elem 5, List [Elem 6]]]

countNest :: Nest a -> Int
countNest (Elem x) = 1
countNest (List xs) = sum $ map countNest xs

答案 1 :(得分:4)

  

让我们说我已经嵌套了lsit:[1,[2,3,4],[5,[6]]]

您无法获得该列表。它不会进行类型检查。尝试在GHCi中单独输入;它会向你吐出一条错误信息。由于这个输入不存在于第一位,因此尝试编写一个函数来处理它是一个注定要失败的努力。

相反,您需要为此定义自定义数据类型。请参阅其他答案。

答案 2 :(得分:0)

正如其他人所说,最简单的方法是使用不同的数据结构,例如定义的tree NovaDenizen。但是,正如您所知,Haskell的类型系统支持各种创建“列表”的方法,其中元素具有不同的类型:请参阅https://wiki.haskell.org/Heterogenous_collections