Haskell 实现`MyMonad Free f`

Haskell 实现`MyMonad Free f`,haskell,Haskell,Typeclassopedia定义了自由monad数据类型 无数据f a=变量a |节点(f(自由f a)) 鉴于: class (MyMonad m) where ret :: a -> m a flatMap :: m a -> (a -> m b) -> m b 下面是我在实现这个typeclass的MyMonad实例方面的不完整尝试 instance Functor f => MyMonad (Free f) whe

Typeclassopedia定义了
自由monad
数据类型

无数据f a=变量a |节点(f(自由f a))

鉴于:

class (MyMonad m) where
    ret     :: a         -> m a
    flatMap :: m a -> (a -> m b) -> m b
下面是我在实现这个typeclass的
MyMonad
实例方面的不完整尝试

instance Functor f => MyMonad (Free f) where
  ret                 = Var
  flatMap (Var x)  f  = f x 
  flatMap (Node xs) f = error
请帮我解释一下
>=
/binding在
免费
单子上意味着什么


当我与
Applicative(Free f)
斗争时,我被鼓励尝试实现
Monad
实例。

在这种情况下,可以帮助我如何继续。它们给出了尚未实现的“洞”应该具有的类型的信息

在定义中使用键入的孔而不是
错误

instance Functor f => MyMonad (Free f) where
    ret                 = Var
    flatMap (Var x)  g  = f x
    flatMap (Node xs) g = _
给出如下错误消息(此处简化):

那个洞里的
freeb
。。。它应该有哪个构造函数<代码>变量或
节点

现在,
Free a
类型的值就像一棵树,它的叶子上有
a
类型的值(
Var
构造函数),其分支节点由functor
f
塑造

什么是免费的?把它想象成是把一棵树“嫁接”到每一片叶子上。这些新树是使用传递给
>=
的函数从叶子中的值构造的

这有助于我们继续:现在我们知道
flatMap(Node xs)f=.
模式右侧的构造函数必须是
Node
,因为“嫁接”到树上的新事物不会将已经存在的节点折叠成树叶,它只会将树叶扩展成全新的树

仍在使用类型孔:

instance Functor f => MyMonad (Free f) where
    ret                 = Var
    flatMap (Var x)  g  = f x
    flatMap (Node xs) g = Node _

Found hole `_' with type: f (Free f b)
...
Relevant bindings include
g :: a -> Free f b (bound at Main.hs:10:21)
xs :: f (Free f a) (bound at Main.hs:10:17)
xs
中,我们有一个
freea
封装在
f
中,但是
f
是一个函子,我们可以很容易地映射到它上面


但是如何将
freeffa
转换成孔所需的
freefb
?直观地说,这个
freeffa
将比
>=
开始时的“更小”,因为我们已经去掉了一个“分支节点”。也许它甚至是一个叶节点,就像其他模式匹配覆盖的情况一样!这建议使用某种类型的递归。

在这种情况下,可以帮助您继续。它们给出了尚未实现的“洞”应该具有的类型的信息

在定义中使用键入的孔而不是
错误

instance Functor f => MyMonad (Free f) where
    ret                 = Var
    flatMap (Var x)  g  = f x
    flatMap (Node xs) g = _
给出如下错误消息(此处简化):

那个洞里的
freeb
。。。它应该有哪个构造函数<代码>变量或
节点

现在,
Free a
类型的值就像一棵树,它的叶子上有
a
类型的值(
Var
构造函数),其分支节点由functor
f
塑造

什么是免费的?把它想象成是把一棵树“嫁接”到每一片叶子上。这些新树是使用传递给
>=
的函数从叶子中的值构造的

这有助于我们继续:现在我们知道
flatMap(Node xs)f=.
模式右侧的构造函数必须是
Node
,因为“嫁接”到树上的新事物不会将已经存在的节点折叠成树叶,它只会将树叶扩展成全新的树

仍在使用类型孔:

instance Functor f => MyMonad (Free f) where
    ret                 = Var
    flatMap (Var x)  g  = f x
    flatMap (Node xs) g = Node _

Found hole `_' with type: f (Free f b)
...
Relevant bindings include
g :: a -> Free f b (bound at Main.hs:10:21)
xs :: f (Free f a) (bound at Main.hs:10:17)
xs
中,我们有一个
freea
封装在
f
中,但是
f
是一个函子,我们可以很容易地映射到它上面


但是如何将
freeffa
转换成孔所需的
freefb
?直观地说,这个
freeffa
将比
>=
开始时的“更小”,因为我们已经去掉了一个“分支节点”。也许它甚至是一个叶节点,就像其他模式匹配覆盖的情况一样!这建议使用某种递归。

从实现
Functor
实例开始。然后请注意,一般来说,monad可以被描述为一个支持
return
join::m(ma)->ma
的函子。您可以看到如何使用
=实现
join
吗?从实现
Functor
实例开始。然后请注意,一般来说,monad可以被描述为一个支持
return
join::m(ma)->ma
的函子。您可以看到如何使用
=
join :: Functor f => Free f (Free f a) -> Free f a
join (Var a) = a
join (Node m) = Node (fmap join m)