gpt4 book ai didi

Haskell - 将联合列表转换为列表元组

转载 作者:行者123 更新时间:2023-12-04 11:56:30 25 4
gpt4 key购买 nike

我正在寻找一种将列表转换为 n 元组的方法,其中一个列表用于不相交联合中的 n 个构造函数中的每一个。标准库专门为 Either 定义了一个类似的函数。年代:

partitionEithers :: [Either a b] -> ([a], [b])
我正在寻找解决具有以下要求的广义问题的技术:
  • 写起来方便
  • 尽可能少的样板
  • 一次性处理列表
  • 允许使用数据类型泛型、元编程、现有库等

  • 例子
    这是一个包含两个建议解决方案的示例规范:
    partitionSum :: [MySum] -> ([A], [B], [C], [D])

    data MySum
    = CaseA A
    | CaseB B
    | CaseC C
    | CaseD D

    data A = A deriving Show
    data B = B deriving Show
    data C = C deriving Show
    data D = D deriving Show

    -- expect "([A,A],[B,B,B],[],[D])"
    test :: IO ()
    test = print . partitionSum $
    [CaseD D, CaseB B, CaseA A, CaseA A, CaseB B, CaseB B]
    第一次尝试:遍历列表 n 次的 n 列表推导。
    partitionSum1 :: [MySum] -> ([A], [B], [C], [D])
    partitionSum1 xs =
    ( [a | CaseA a <- xs]
    , [b | CaseB b <- xs]
    , [c | CaseC c <- xs]
    , [d | CaseD d <- xs]
    )
    第二次尝试:单次遍历输入列表。我必须手动将状态穿过折叠,这使得解决方案有点重复和烦人。
    partitionSum2 :: [MySum] -> ([A], [B], [C], [D])
    partitionSum2 = foldr f ([], [], [], [])
    where
    f x (as, bs, cs, ds) =
    case x of
    CaseA a -> (a : as, bs, cs, ds)
    CaseB b -> (as, b : bs, cs, ds)
    CaseC c -> (as, bs, c : cs, ds)
    CaseD d -> (as, bs, cs, d : ds)

    最佳答案

    除了 Representable answer :

    看到 foldr f ([], [], [], []) 后想到的一件事是定义一个幺半群,其中 nil 的情况是 mempty

    {-# DerivingVia #-}
    ..
    import GHC.Generics (Generically(..), ..)

    type Classify :: Type
    type Classify = C [A] [B] [C] [D]
    deriving
    stock Generic

    deriving (Semigroup, Monoid)
    via Generically Classify

    -- mempty = C [] [] [] []
    -- C as bs cs ds <> C as1 bs1 cd1 ds1 = C (as ++ as1) (bs ++ bs1) (cs ++ cs1) (ds ++ ds1)
    Generically 将从 GHC.Generics 导出在将来。它定义了 Classify通过通用的逐点提升作为半群和幺半群。
    有了这个,你只需要一个分类器函数,它对 MySum 进行分类。进入 Classify你可以定义 partition根据 foldMap
    classify :: MySum -> Classify
    classify = \case
    SumA a -> C [a] [] [] []
    SumB b -> C [] [b] [] []
    SumC c -> C [] [] [c] []
    SumD d -> C [] [] [] [d]

    partition :: Foldable f => f MySum -> Classify
    partition = foldMap classify

    关于Haskell - 将联合列表转换为列表元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68958369/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com