【问题标题】:A List of Recursive Data Structure as Function Input作为函数输入的递归数据结构列表
【发布时间】:2017-04-22 04:58:48
【问题描述】:

我在 Haskell 中定义了一个递归数据结构:

data NestedList a = Element a | SubList [NestedList a]

然后我想定义一个flatten 函数,它将获取一个 NestedList 列表并返回扁平化结果,例如:

Input: [Element 1, SubList [Element 2, SubList [] ]]
Output: [Element 1, Element 2].

但是,我对函数的定义是不正确的:

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

根据这个定义,我的函数将像这样工作:

flatten (SubList [Element 1, SubList []])

而不是

flatten [Element 1, SubList []]

所以这个flatten不能接受我上面提到的输入,那么我应该如何定义flatten让它接受像[Element 1, SubList [Element 2, SubList []]]这样的输入?

【问题讨论】:

  • 这不是你想要的定义吗?在我看来它工作得很好 - 结果将是[1],如果你想将该结果的每个元素包装在Element(无论出于何种原因......),那么只需执行map Element . flatten。跨度>
  • 一个更简单的等效定义是将最后两个子句替换为flatten (Sublist xs) = xs >>= flatten
  • FWIW,NestedList 只是 Free []flatten 只是来自 instance Foldable f => Foldable (Free f)instance Foldable []toList
  • 如果这不是你想要的,你想要什么?
  • 我的意思是我需要像 [Element 1, SubList []] 这样的输入而不是 SubList [Element 1, SubList []]。

标签: haskell types


【解决方案1】:

我怀疑您正在寻找以下内容:

flatten :: [NestedList a] -> [NestedList a]
flatten (Element a  : rest) = Element a : flatten rest
flatten (SubList xs : rest) = flatten xs ++ flatten rest
flatten [] = []

这似乎可以做你想做的事:

> flatten [Element 1, SubList []]
[Element 1]
> flatten [Element 1, SubList [Element 2, SubList []]]
[Element 1,Element 2]
>

【讨论】:

    【解决方案2】:

    如果您想将NestedList 扁平化为扁平化NestedList 而不是普通列表,您可以定义一个单独的函数fromList :: [a] -> NestedList a,该函数从普通列表构建扁平化嵌套列表。

    fromList :: [a] -> NestedList a
    fromList l = SubList (toElems l)
      where
        toElems :: [a] -> [SubList a]
        toElems (x:xs) = Element x : toElems xs
        toElems [] = []
    

    或者干脆

    fromList = SubList . map Element
    

    然后写

    flattenNested :: NestedList a -> NestedList a
    flattenNested = fromList . flatten
    

    当然,您也可以将flatten 本身更简单地写为:

    flatten :: NestedList a -> [a]
    flatten (Element a) = [a]
    flatten (SubList xs) = concat (map flatten xs)
    

    甚至是这些越来越书呆子的替代品之一:

    flatten (SubList xs) = concatMap flatten xs
    

    由于concatMap=<< 相同:

    flatten (SubList xs) = flatten =<< xs
    

    由于NestedListFree [] 同构:

    flatten :: Free [] a -> [a]
    flatten (Pure a) = [a]
    flatten (Free xs) = flatten =<< xs
    

    或者通过(ab)进一步使用这种关系:

    flatten :: Free [] a -> [a]
    flatten = toList
    

    【讨论】:

      猜你喜欢
      • 2018-08-27
      • 2016-03-18
      • 2020-04-19
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多