Я играл вокруг с свободной, как идеи, и нашел это:Есть ли обобщение этих Free-подобных конструкций?
{-# LANGUAGE RankNTypes #-}
data Monoid m = Monoid { mempty :: m, mappend :: m -> m -> m }
data Generator a m = Generator { monoid :: Monoid m, singleton :: a -> m }
newtype Free f = Free { getFree :: forall s. f s -> s }
mkMonoid :: (forall s. f s -> Monoid s) -> Monoid (Free f)
mkMonoid f = Monoid {
mempty = Free (mempty . f),
mappend = \a b -> Free $ \s -> mappend (f s) (getFree a s) (getFree b s)
}
freeMonoid :: Monoid (Free Monoid)
freeMonoid = mkMonoid id
mkGenerator :: (forall s. f s -> Generator a s) -> Generator a (Free f)
mkGenerator f = Generator {
monoid = mkMonoid (monoid . f),
singleton = \x -> Free $ \s -> singleton (f s) x
}
freeGenerator :: Generator a (Free (Generator a))
freeGenerator = mkGenerator id
Я хотел бы найти условия, при которых я мог бы написать несильно:
mkFree :: (??? f) => f (Free f)
, но я не смог найти значимую структуру для f
(кроме тривиальной, в которой mkFree
- это метод ???
), который позволил бы записать эту функцию. В частности, мой эстетический смысл предпочел бы, если бы эта структура не упоминала тип Free
.
Кто-нибудь видел что-то подобное раньше? Возможно ли это обобщение? Есть ли известное обобщение в том направлении, о котором я еще не думал?
У меня есть это на Hackage (church encoded version быть точными.): Http://hackage.haskell.org/ пакет/свободные функторы-0.1.1, но я не думаю, что это то, что вы хотите? –
Правильно, после сопоставления с вашим пакетом, я думаю, я понимаю, чего вы хотите. В переводе это будет автоматически генерировать экземпляр «Monoid (Free Monoid a)» или вообще экземпляр «c (Free c a)». F.E. экземпляр «Num» здесь: https://github.com/sjoerdvisscher/free-functors/blob/master/examples/FreeNum.hs. Это в основном 'liftAn' плюс некоторый шум для простых случаев, который должен быть разрешен с помощью некоторого шаблона haskell. Но я думаю, что вполне общий случай довольно сложный. –
@SjoerdVisscher, это тот шум, который меня интересует (вот почему я использую типы данных, а не классы здесь). Он похож на «Traversable», но он работает и с отрицательными вхождениями параметра. Мне было интересно, есть ли алгебраическое свойство (например, «Traversable»), а не структурные (подписи подписи на интроспекции), из которых этот экземпляр может быть сгенерирован. – luqui