Я использую barbies-th
, чтобы превратить тип записи в тип данных с более высоким родом:
declareBareB [d|
data Foo = MkFoo
{ field1 :: Int
, field2 :: Bool
} |]
Затем я могу написать функцию для pu sh любой аппликативный эффект в отдельные поля:
bdistribute :: (Applicative f) => f (Foo Bare Identity) -> Foo Covered f
bdistribute foo = MkFoo
{ field1 = field1 <$> foo
, field2 = field2 <$> foo
}
Но мне кажется, что я должен написать bdistribute
раз и навсегда для всех HKD в стиле Barb ie. Другими словами, я ищу двойника Хигглиди construct
. У Хиггли есть два метода в классе типов 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