免费monad和免费操作

时间:2016-01-03 10:31:42

标签: haskell monads category-theory free-monad

描述Free monad的一种方法是说它是endofunctors类别(某些类别C)中的 initial monoid,其对象是来自{{1}的endofunctors } C,箭头是它们之间的自然变换。如果我们将C作为C,那么endofunctor就是haskell中的Hask,它是来自Functor的仿函数,其中* -> *表示{的对象{1}}

根据初始性,从*中的endofunctor Hask到monoid t的任何地图都会导致从mEnd(Hask)的地图。

否则,从Functor Free t到Monad m的任何自然转换都会导致从tm的自然转换

我原本希望能够编写一个函数

Free t

但是这不能统一,而以下工作

m

或带签名的概括

free :: (Functor t, Monad m) => (∀ a. t a → m a) → (∀ a. Free t a → m a)
free f (Pure  a) = return a
free f (Free (tfta :: t (Free t a))) =
    f (fmap (free f) tfta) 

我是否在类别理论或Haskell的翻译中犯了错误?

我有兴趣在这里听到一些智慧......

PS:启用该代码的代码

free :: (Functor t, Monad m) => (t (m a) → m a) → (Free t a → m a)
free f (Pure  a) = return a
free f (Free (tfta :: t (Free t a))) =
    f (fmap (free f) tfta)

2 个答案:

答案 0 :(得分:7)

Haskell翻译似乎错了。一个很大的提示是你的free实现并没有在任何地方使用monadic bind(或join)。您可以使用以下定义找到free foldFree

free :: Monad m => (forall x. t x -> m x) -> (forall a. Free t a -> m a)
free f (Pure a)  = return a
free f (Free fs) = f fs >>= free f

关键点是f专门针对t (Free t a) -> m (Free t a),从而一举消除了一个Free层。

答案 1 :(得分:3)

我不了解类别理论部分,但是Haskell部分绝对不能用原始实现和原始类型签名进行良好的输入。

鉴于

Free tfta

当你在tfta :: t (Free t a) f :: forall a. t a -> m a free :: (forall a. t a -> m a) -> forall a. Free t a -> m a 上进行模式匹配时,你会得到

free f :: forall a. Free t a -> m a

因此

fmap (free f) :: forall a. t (Free t a) -> t (m a) 

导致

t (m a)

为了能够将m a折叠到您想要的f,您需要在其上应用t(以及#34;将m变为m")然后利用f . fmap (free f) :: forall a. t (Free t a) -> m (m a) join . f . fmap (free f) :: forall a. t (Free t a) -> m a 是Monad的事实:

free

这意味着您可以通过更改{-# LANGUAGE RankNTypes, UnicodeSyntax #-} import Control.Monad.Free import Control.Monad free :: (Functor t, Monad m) => (∀ a. t a → m a) → (∀ a. Free t a → m a) free f (Pure a) = return a free f (Free tfta) = join . f . fmap (free f) $ tfta 的第二个分支来修复原始定义:

var john = {

    peter: {},

    one: function() { alert('one'); },

    two: function() {
        peter.handler = function() {
            john.one(); // JS cannot find one(). one() undefined.

            Console.log(this); // object peter
        }

        Console.log(this); // object john
    }
}

这可能是你想要的,但也许可能是你想要的:)