这些类似Free的结构是否有概括?

时间:2013-02-13 11:40:19

标签: haskell category-theory free-monad

我正在玩着类似自由的想法,并发现了这个:

{-# 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类型,我的审美意识会更喜欢。

有没有人见过这样的东西?这种概括可能吗?在我尚未想到的方向上有一个已知的概括吗?

1 个答案:

答案 0 :(得分:8)

与通用代数的联系是一个很好的起点,在阅读之后,一切都落到了位置。我们正在寻找的是F代数:

type Alg f x = f x -> x

用于任何(endo)仿函数f。例如,对于Monoid代数,仿函数是:

data MonoidF m = MEmpty | MAppend m m deriving Functor

对于任何Monoid实例,都有明显的幺半群​​代数:

monoidAlg :: Monoid m => Alg MonoidF m
monoidAlg MEmpty = mempty
monoidAlg (MAppend a b) = mappend a b

现在我们可以从free-functors包中获取free functor定义,并用f-algebra替换类约束:

newtype Free f a = Free { runFree :: forall b. Alg f b -> (a -> b) -> b }

在某种意义上,自由仿函数是将任何集a转换为代数的最佳方法。这是如何:

unit :: a -> Free f a
unit a = Free $ \_ k -> k a

这是最好的方法,因为通过任何其他方式将a转换为代数b,我们可以将免费代数中的函数赋予b

rightAdjunct :: Functor f => Alg f b -> (a -> b) -> Free f a -> b
rightAdjunct alg k (Free f) = f alg k

剩下的就是实际显示自由仿函数创建了一个f代数(这就是你要求的):

freeAlg :: Functor f => Alg f (Free f a)
freeAlg ff = Free $ \alg k -> alg (fmap (rightAdjunct alg k) ff)

稍微解释一下:ff的类型为f (Free f a),我们需要构建一个Free f a。如果我们可以构建b,给定alg :: f b -> bk :: a -> b,我们就可以做到这一点。因此,如果我们可以将alg包含的每个ff映射到Free f a,我们就可以将b应用于rightAdjunct,但这正是algk的作用}和Free f

正如您可能已经猜到的那样,f是仿函数instance Functor f => Monad (Free f) where return = unit m >>= f = rightAdjunct freeAlg f m 上的免费monad(确切地说是church encoded version。)

{{1}}