我正在玩一些类似免费的想法,发现了这个:
{-# 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
类型,我的审美会更喜欢。
有没有人见过这样的东西?这种概括可能吗?在我还没有想到的方向上是否有一个已知的概括?