在Haskell中实现类似concat的函数,而不使用任何前奏函数

时间:2016-09-15 23:52:00

标签: haskell

我试图实现一个可以展平列表列表的函数。只有一层深。所以,如果我打电话给flatten [[3],[3, 5]],我会得到[3,3,5]。这是我的代码:

flatten :: [[a]] -> [a]
flatten [[]] = []
flatten [(x:xs)] = 
 flatten [xs] ++ [x]

当我致电flatten [[3], [5]]

时,我收到错误“函数展平中的非详尽模式”

3 个答案:

答案 0 :(得分:6)

处理列表时需要考虑两种基本模式。任何列表必须是:

  • 空列表([]
  • cons小区(_:_

由于concat作用于列表列表,我们可以通过列表的第一个元素上的模式匹配将第二种情况分解为两种情况,这必须是

  • 空列表([]:_
  • cons单元格((_:_):_ 1

这给了我们三种模式:

concat [] = ...
concat ([]:xss) = ...
concat ((x:xs):xss) = ...

了解每个列表必须如何完全匹配这些模式

现在,鉴于细分,请查看您是否只能使用concatxxsxss:来实施[] ,和concat本身。

  1. 请注意,(_:_):__:_:_的格式不同,后者更明确地写为_:(_:_)。前者是列表列表头部的非空列表的模式。后者是至少两个元素列表的模式。

答案 1 :(得分:2)

可能的解决方案:

flatten [] = []
flatten ([]:vs) = flatten vs
flatten ((x:xs):vs) = x:flatten (xs:vs)

答案 2 :(得分:0)

您使用的图案不正确。 在您的情况下,[smth]将列表与一个元素匹配:

[[]] - 是一个包含一个空列表的列表 [(x:xs)] - 是包含一个元素的列表 - 列表(x:xs),它不是空的

因此两种情况都匹配单元素列表。这就是为什么函数在[[3], [5]]

上失败的原因

显然,你可能想要其他两种情况:空([])而非空列表((x:xs)

flatten :: [[a]] -> [a]
flatten [] = []
flatten (x:xs)