私は自由なアイデアで遊んでいて、これを見つけました:
{-# 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
誰かが前にこのようなものを見たことがありますか? この一般化は可能ですか?私がまだ考えていない方向への既知の一般化はありますか?