mxx*_*xxk 35 monads haskell monoids
我正在努力了解这背后的动机MonadPlus.如果已经有类型Monad和Monoid?为什么有必要?
当然,实例Monoid是具体类型,而实例Monad需要单个类型参数.(有关有用的解释,请参阅Monoid与MonadPlus.)但是你不能重写任何类型约束
(MonadPlus m) => ...
Run Code Online (Sandbox Code Playgroud)
作为Monad和Monoid?的组合?
(Monad m, Monoid (m a)) => ...
Run Code Online (Sandbox Code Playgroud)
例如,guard从中获取功能Control.Monad.它的实施是:
guard :: (MonadPlus m) => Bool -> m ()
guard True = return ()
guard False = mzero
Run Code Online (Sandbox Code Playgroud)
我只能使用Monad和实现它Monoid:
guard' :: (Monad m, Monoid (m ())) => Bool -> m ()
guard' True = return ()
guard' False = mempty
Run Code Online (Sandbox Code Playgroud)
有人可以澄清MonadPlus和Monad+ 之间的真正区别Monoid吗?
Tox*_*ris 34
但是你不能重写任何类型约束
Run Code Online (Sandbox Code Playgroud)(MonadPlus m) => ...作为Monad和Monoid的组合?
在你回答的问题的最佳答案中,对于MonadPlus与Monoid的法律已经有了很好的解释.但即使我们忽略了类型规则,也存在差异.
Monoid (m a) => ...意味着m a必须是a调用者选择的一个特定的幺半群,但MonadPlus m意味着m a必须是所有人的幺半群a.因此MonadPlus a更灵活,这种灵活性有助于四种情况:
如果我们不想告诉来电者a我们打算使用什么.
MonadPlus m => ...代替Monoid (m SecretType) => ...
如果我们想要使用多个不同的a.
MonadPlus m => ...代替(Monoid (m Type1), Monoid (m Type2), ...) => ...
如果我们想要使用无限多的不同a.
MonadPlus m => ...而不是不可能.
如果我们不知道a我们需要什么.
MonadPlus m => ...而不是不可能.
您guard'的Monoid m a类型与您的类型不符.
如果你的意思是Monoid (m a),那么你需要定义什么mempty是m ().一旦你完成了,你就定义了一个MonadPlus.
换句话说,MonadPlus定义两个操作:mzero并且mplus满足两个规则:mzero相对于中性mplus,并且mplus是关联的.这满足的定义Monoid,这样mzero是mempty和mplus是mappend.
不同之处在于它MonadPlus m是m a任何一个幺半群a,但Monoid m仅定义了一个幺半群m.你的guard'作品,因为你只需要m成为一个Monoid只为().但MonadPlus它更强大,它声称m a对任何人都是幺半群a.
随着该QuantifiedConstraints语言扩展,你可以表达的Monoid (m a)对象必须是跨越所有的选择一致a:
{-# LANGUAGE QuantifiedConstraints #-}
class (Monad m, forall a. Monoid (m a)) => MonadPlus m
mzero :: (MonadPlus m) => m a
mzero = mempty
mplus :: (MonadPlus m) => m a -> m a -> m a
mplus = mappend
Run Code Online (Sandbox Code Playgroud)
Alternatively,我们可以MonadPlus为所有这样的幺半群单子通用地实现“真实”类:
{-# LANGUAGE GeneralizedNewtypeDeriving, DerivingStrategies, QuantifiedConstraints #-}
{-# LANGUAGE UndecidableInstances #-}
import Control.Monad
import Control.Applicative
newtype MonoidMonad m a = MonoidMonad{ runMonoidMonad :: m a }
deriving (Functor, Applicative, Monad)
instance (Applicative m, forall a. Monoid (m a)) => Alternative (MonoidMonad m) where
empty = MonoidMonad mempty
(MonoidMonad x) <|> (MonoidMonad y) = MonoidMonad (x <> y)
instance (Monad m, forall a. Monoid (m a)) => MonadPlus (MonoidMonad m)
Run Code Online (Sandbox Code Playgroud)
请注意,根据您对 的选择m,这可能会或可能不会给您带来MonadPlus您期望的结果;例如,MonoidMonad []实际上与[]; 但是对于Maybe,Monoid实例通过人为地给它一个恒等元素来提升一些潜在的半群,而MonadPlus实例是左偏选择;所以我们必须使用MonoidMonad First而不是MonoidMonad Maybe来获得正确的实例。
| 归档时间: |
|
| 查看次数: |
1654 次 |
| 最近记录: |