假设我已经嵌套了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中做到这一点?
答案 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