我正在使用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
为所有芭比娃娃式的HKD一劳永逸地写作。换句话说,我正在寻找希格莱迪(Higgledy's)的对偶construct
。Higgledy在typeclass中具有以下两个方法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
我最终在
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
这是否暗示某种具有代表性的事物
Distributive
?我认为这
shape
就是事实:DistributiveB
类型是产品的证明。