如何扁平化嵌套的NonEmpty结构且全程保持为NonEmpty类型
NonEmpty 嵌套结构的扁平化方案
我们需要实现的目标函数类型为 NonEmpty (NonEmpty a) -> NonEmpty a,全程在 NonEmpty 类型体系内操作,无需转换为普通列表。
方案1:使用标准库自带实现
NonEmpty 类型的 Monad 实例提供的 join 方法刚好匹配需求,内部原生实现了非空拼接逻辑,没有中间普通列表转换:
import Data.List.NonEmpty (NonEmpty(..)) import qualified Control.Monad as Monad -- 示例输入 nestedNE :: NonEmpty (NonEmpty Int) nestedNE = (1 :| [2,3]) :| [4 :| [5], 6 :| []] flattenedNE :: NonEmpty Int flattenedNE = Monad.join nestedNE -- 运行结果:1 :| [2,3,4,5,6]
方案2:手动实现无依赖版本
如果不想引入 Monad 依赖,可基于 NonEmpty 的 Semigroup 拼接操作自行实现,逻辑非常直观:
import Data.List.NonEmpty (NonEmpty(..), (<>)) flattenNE :: NonEmpty (NonEmpty a) -> NonEmpty a flattenNE (firstSubNE :| restSubNEs) = foldl (<>) firstSubNE restSubNEs
实现逻辑:
- 先取出嵌套结构的第一个非空列表作为初始拼接基准
- 遍历剩余的所有非空列表,依次用
<>操作拼接到基准上 - 由于所有操作对象都是 NonEmpty 类型,拼接结果始终保证非空,全程不会产生普通列表中间值
内容的提问来源于stack exchange,提问作者thirsty
相关产品推荐
相关产品推荐

