Monad的免费Monad

时间:2013-02-06 22:37:02

标签: haskell free-monad

x >>= f是否等同于retract (liftF x >>= liftF . f)

那就是,一个免费monad构建的monad实例来自一个Functor,它也是一个Monad将拥有与原Monad相同的monad实例?

2 个答案:

答案 0 :(得分:9)

我不知道你对retract的定义是什么,但是给出了

retract :: Monad m => Free m a -> m a
retract (Pure a) = return a
retract (Impure fx) = fx >>= retract

liftF :: Functor f => f a -> Free f a
liftF fx = Impure (fmap Pure fx)

请注意(证明可能是错误的,手动完成并且没有检查过它们)

retract $ liftF x
= retract (Impure (fmap Pure x))
= (fmap Pure x) >>= retract
= (x >>= return . Pure) >>= retract
= x >>= \y -> (return $ Pure y) >>= retract
= x >>= \y -> (retract (Pure y))
= x >>= \y -> return y
= x >>= return
= x

所以你有

retract (liftF x >>= liftF . f)
= retract ((Impure (fmap Pure x)) >>= liftF . f)
= retract $ Impure $ fmap (>>= liftF . f) $ fmap Pure x
= (fmap (>>= liftF . f) $ fmap Pure x) >>= retract
= (fmap (\y -> Pure y >>= liftF . f) x) >>= retract
= (fmap (liftF . f) x) >>= retract
= (liftM (liftF . f) x) >>= retract
= (x >>= return . liftF . f) >>= retract
= x >>= (\y -> (return $ liftF $ f y >>=  retract)
= x >>= (\y -> retract $ liftF $ f y)
= x >>= (\y -> retract . liftF $ f y)
= x >>= (\y -> f y)
= x >>= f

这并不意味着Free m am a同构,只是retract确实见证了撤退。请注意,liftF 是monad态射(return未转到return)。免费是仿函数类别中的仿函数,但它不是monad类别中的monad(尽管retract看起来很像joinliftF看起来很像{{1} })。

编辑:请注意,撤回意味着一种等价。定义

return

然后考虑商类型 ~ : Free m a -> Free m a -> Prop a ~ b = (retract a) ==_(m a) (retract b) 。我断言这种类型与Free m a/~同构。由于m a因为(liftF (retract x)) ~ x。因此,monad上的自由monad就是monad加上一些额外的数据。这与(retract . liftF . retract $ x) ==_(m a) retract x[m]“基本相同”的声明完全相同,m m是一个幺半群。

答案 1 :(得分:4)

  

那就是,一个免费monad构建的monad实例来自一个Functor,它也是一个Monad将拥有与原Monad相同的monad实例?

没有。 任何仿函数的免费monad是monad。因此,当它存在时,它无法神奇地了解Monad实例。并且它也不能“猜测”它,因为同一个仿函数可能以不同的方式成为Monad(例如不同幺半群的作家monad)。

另一个原因是,询问这两个monad是否具有等效实例没有多大意义,因为它们甚至不是同构类型。例如,考虑作者monad上的免费monad。它将是一个类似列表的结构。这两个实例是等价的意思是什么?

不同monad实例的示例

如果上面的描述不清楚,这里是一个具有许多可能的Monad实例的类型的例子。

data M a = M Integer a

bindUsing :: (Integer -> Integer -> Integer) -> M a -> (a -> M b) -> M b
bindUsing f (M n a) k =
  let M m b = k a
  in M (f m n) b

-- Any of the below instances is a valid Monad instance
instance Monad M where
  return x = M 0 x
  (>>=) = bindUsing (+)

instance Monad M where
  return x = M 1 x
  (>>=) = bindUsing (*)