gpt4 book ai didi

haskell - 处理由仿函数参数化的数据类型

转载 作者:行者123 更新时间:2023-12-04 18:11:09 50 4
gpt4 key购买 nike

我最近定义了一个类型,我可能无法计算其字段:

data Foo = Foo {x, y :: Int, others :: NonEmpty Int}

data Input

computeX, computeY :: Input -> Maybe Int
computeOthers :: Input -> Maybe (NonEmpty Int)
现在,我可能会做的一件显而易见的事情就是使用 liftA3 :
foo :: Input -> Maybe Foo
foo i = liftA3 Foo (computeX i) (computeY i) (computeOthers i)
这很好用,但我认为概括 Foo 可能会很有趣持有 Maybe s,然后转换一种类型的 Foo给另一个。在一些类似的情况下,我可以给 Foo键入类型参数并派生 Traversable。然后在创建 Foo (Maybe Int) 之后, 我可以用 sequenceA :: Foo (Maybe Int) -> Maybe (Foo Int) 一次反转整个事情.但这在这里不起作用,因为我的函数没有给我一个 NonEmpty (Maybe Int) ,它给了我一个 Maybe (NonEmpty Int) .
所以我想我会尝试用仿函数进行参数化:
data Foo f = Foo {x, y :: f Int, others :: f (NonEmpty Int)}
但接下来的问题是,我该如何转 Foo Maybe变成 Maybe (Foo Identity) ?显然,我可以手动编写该函数:它与 liftA3 同构。上面的东西。但是对于这种高阶类型是否有一些平行的 Traversable ,以便我可以对这个问题应用更通用的函数,而不是用定制函数重新做它?

最佳答案

此类数据类型称为“高级数据”(HKD)。操作它们通常使用泛型或模板 Haskell 完成。
有像 higgledy 这样的库它为港元提供内置功能。我相信 construct 是您正在寻找的功能:

{-# LANGUAGE DeriveGeneric #-}

import Data.Generic.HKD
import GHC.Generics
import Data.Monoid

data Foo = Foo { x, y :: Int, z :: [Int] }
deriving (Generic, Show)

emptyFoo :: HKD Foo Last
emptyFoo = mempty

sampleFoo :: HKD Foo Last
sampleFoo = deconstruct (Foo 1 2 [3])

emptyFoo' :: Last Foo
emptyFoo' = construct emptyFoo

sampleFoo' :: Last Foo
sampleFoo' = construct sampleFoo

main = do
print emptyFoo'
print sampleFoo'
这将打印:
Last {getLast = Nothing}
Last {getLast = Just (Foo {x = 1, y = 2, z = [3])}

编辑:我刚刚发现一个更受欢迎的库是 barbies (higgledy 也取决于芭比娃娃)。您正在寻找的函数也作为 btraverse 的应用程序存在于该库中。 :
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}

import Data.List.NonEmpty
import Barbies
import GHC.Generics
import Data.Functor.Identity

data Foo f = Foo {x, y :: f Int, others :: f (NonEmpty Int)}
deriving (Generic, FunctorB, TraversableB, ConstraintsB)

deriving instance AllBF Show f Foo => Show (Foo f)

f :: Applicative f => Foo f -> f (Foo Identity)
f = btraverse (fmap Identity)

main :: IO ()
main = do
print (f (Foo (Just 1) (Just 2) (Just (3 :| []))))
这打印:
Just (Foo {x = Identity 1, y = Identity 2, others = Identity (3 :| [])})

关于haskell - 处理由仿函数参数化的数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70258416/

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