问题描述
如何展平这样的嵌套列表:
How can I flatten a nested list like this:
[1, 2, 3, 4] == flatten [[[1,2],[3]],[[4]]]
推荐答案
因为没有其他人给出过这个,所以可以定义一个函数,通过使用 MultiParamTypeClasses 来展平任意深度的列表.我实际上并没有发现它有用,但希望它可以被认为是一个有趣的黑客.我从 Oleg 的多变量函数实现中得到了这个想法.
Since nobody else has given this, it is possible to define a function which will flatten lists of an arbitrary depth by using MultiParamTypeClasses. I haven't actually found it useful, but hopefully it could be considered an interesting hack. I got the idea from Oleg's polyvariadic function implementation.
{-# LANGUAGE MultiParamTypeClasses, OverlappingInstances, FlexibleInstances #-}
module Flatten where
class Flatten i o where
flatten :: [i] -> [o]
instance Flatten a a where
flatten = id
instance Flatten i o => Flatten [i] o where
flatten = concatMap flatten
现在如果你加载它并在 ghci 中运行:
Now if you load it and run in ghci:
*Flatten> let g = [1..5]
*Flatten> flatten g :: [Integer]
[1,2,3,4,5]
*Flatten> let h = [[1,2,3],[4,5]]
*Flatten> flatten h :: [Integer]
[1,2,3,4,5]
*Flatten> let i = [[[1,2],[3]],[],[[4,5],[6]]]
*Flatten> :t i
i :: [[[Integer]]]
*Flatten> flatten i :: [Integer]
[1,2,3,4,5,6]
请注意,通常需要提供结果类型注释,否则 ghc 无法确定在哪里停止递归应用 flatten
类方法.但是,如果您使用具有单态类型的函数就足够了.
Note that it's usually necessary to provide the result type annotation, because otherwise ghc can't figure out where to stop recursively applying the flatten
class method. If you use a function with a monomorphic type that's sufficient however.
*Flatten> :t sum
sum :: Num a => [a] -> a
*Flatten> sum $ flatten g
<interactive>:1:7:
No instance for (Flatten Integer a0)
arising from a use of `flatten'
Possible fix: add an instance declaration for (Flatten Integer a0)
In the second argument of `($)', namely `flatten g'
In the expression: sum $ flatten g
In an equation for `it': it = sum $ flatten g
*Flatten> let sumInt = sum :: [Integer] -> Integer
*Flatten> sumInt $ flatten g
15
*Flatten> sumInt $ flatten h
15
这篇关于是否有一个函数可以展平嵌套的元素列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!