【问题标题】:Flatten a list of lists展平列表列表
【发布时间】:2012-03-19 10:12:14
【问题描述】:

我必须编写一个扁平化列表的函数。

例如flatten [] = []flatten [1,2,3,4] = [1,2,3,4]flatten [[1,2],[3],4,5]] = [1,2,3,4,5]

我无法根据给定的 flatten 函数匹配类型。

这是我所拥有的:

data A a = B a | C [a] deriving (Show, Eq, Ord)

flatten::(Show a, Eq a, Ord a)=>A a -> A a
flatten (C []) = (C [])
flatten (C (x:xs) ) = (C flatten x) ++ (C flatten xs)
flatten (B a) = (C [a])

据我所知,问题是++ 运算符期望它的两个参数都有一个列表,我试图给它一些A 类型的东西。我添加了 A 类型,因此该函数可以获取单个元素或元素列表。

有没有人知道一种不同的方法来做到这一点,或者解释我可以做些什么来修复类型错误?

【问题讨论】:

  • 我不确定你到底想要什么。也许flatten :: A [a] -> A a; flatten (B xs) = C xs; flatten (C xss) = C (concat xss) 会帮助你?基本上,您不能编写 flatten 以便它获取不同嵌套的列表并对它们执行不同的操作,除非您将它们包装成新类型并通过构造函数区分情况。
  • 你的函数类型应该是[[a]] -> [a]。这意味着flatten [] 有效,flatten [[1,2,3,4]] 有效,但flatten [1,2,3,4] 无效。 [1,2,3,4] 不是列表列表。如果您考虑到这一点并从头开始,摆脱您的特殊类型,您会发现它会容易得多。

标签: list haskell types abstract


【解决方案1】:

通过列表理解展平。

flatten arr = [y | x<- arr, y <- x]

【讨论】:

    【解决方案2】:

    这一个班轮将完成这项工作。尽管正如 Malin 提到的,类型签名不同:

    flatten :: [[a]] -> [a]         
    flatten xs = (\z n -> foldr (\x y -> foldr z y x) n xs) (:) []
    

    简单测试

    frege> li = [[3,4,2],[1,9,9],[5,8]]
    frege> flatten li
    [3,4,2,1,9,9,5,8]
    

    【讨论】:

    • 关键是该函数应该适用于简单列表和嵌套列表。您的作品仅适用于简单列表。
    【解决方案3】:

    首先,A 类型是在正确的轨道上,但我不认为它是完全正确的。您希望它能够展平任意嵌套的列表,因此“A a”类型的值应该能够包含“A a”类型的值:

    data A a = B a | C [A a]
    

    其次,函数的类型应该略有不同。您可能希望它只返回 a 的列表,而不是返回类型为“A a”的值,因为根据定义,该函数始终返回一个平面列表。所以类型签名是这样的:

    flatten :: A a -> [a]
    

    还要注意,不需要类型类约束——这个函数是完全通用的,因为它根本不查看列表的元素。

    这是我的实现:

    flatten (B a) = [a]
    flatten (C []) = []
    flatten (C (x:xs)) = flatten x ++ flatten (C xs)
    

    【讨论】:

    • flatten (B a) = [a]; flatten (C xs) = flatten =&lt;&lt; xs
    【解决方案4】:

    有点不清楚您要的是什么,但展平列表列表是一个标准函数,在前奏中称为concat,类型签名为[[a]] -&gt; [a]

    如果您像上面开始的那样创建嵌套列表的数据类型,也许您想将数据类型调整为如下所示:

     data Lists a = List [a] | ListOfLists [Lists a]
    

    然后你可以将它们展平为一个列表;

     flatten :: Lists a -> [a]
     flatten (List xs) = xs
     flatten (ListOfLists xss) = concatMap flatten xss
    

    作为测试,

     > flatten (ListOfLists [List [1,2],List [3],ListOfLists [List [4],List[5]]])
     [1,2,3,4,5]
    

    【讨论】:

      猜你喜欢
      • 2017-10-09
      • 2016-01-26
      • 2013-04-24
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 2011-09-17
      相关资源
      最近更新 更多