首页 > 解决方案 > 使用 Barbies 或 Higgledy 将应用效果推向 HKD 领域

问题描述

我正在使用barbies-th将记录类型转换为更高种类的数据类型:

declareBareB [d|
  data Foo = MkFoo
      { field1 :: Int
      , field2 :: Bool
      } |]

然后我可以编写一个函数来将任何应用效果推送到各个字段中:

bdistribute :: (Applicative f) => f (Foo Bare Identity) -> Foo Covered f
bdistribute foo = MkFoo
    { field1 = field1 <$> foo
    , field2 = field2 <$> foo
    }

但感觉我应该能够bdistribute一劳永逸地为所有芭比风格的港币写作。换句话说,我正在寻找 Higgledy's 的对偶construct。Higgledy 在类型类中有这两种方法Construct

construct :: HKD structure f -> f structure
deconstruct :: structure -> HKD structure f

但我想

nstruct :: (Applicative f) => f structure -> HKD structure f

下面进行头脑风暴:我刚刚想到的一个想法是,这个问题可以简化为一般地编写以下函数:

shape :: Foo Covered ((->) (Foo Bare Identity))
shape = MkFoo
    { field1 = field1
    , field2 = field2
    }

从那以后我们有了

bdistribute :: (Applicative f) => f (Foo Bare Identity) -> Foo Covered f
bdistribute = bmap (<$> x) shape

更一般地,从shape我们也可以写

bdistribute :: (Functor f, Applicative g, ApplicativeB b, TraversableB b) => f (b g) -> b (Compose f g)
bdistribute x = bmap (\f -> Compose $ fmap f . bsequence' <$> x) shape

标签: haskellgeneric-programminghigher-kinded-types

解决方案


我最终为 Barbies 包添加了一个DistributiveB类型类 ,自 2.0.1.0 起可用:

class FunctorB b => DistributiveB (b :: (k -> Type) -> Type) where
    bdistribute :: Functor f => f (b g) -> b (Compose f g)

要从我原来的问题中恢复shape功能,我们可以使用以下专用版本bdistribute

bdecompose :: DistributiveB b => (a -> b Identity) -> b ((->) a)

这给了我们shape = bdecompose id


推荐阅读