do 符号是否特定于“base:GHC.Base.Monad”?
标准 Monad
类有缺陷并且它实际上应该扩展 Functor
或 Pointed
的想法正在流传。
我不一定声称这是正确的做法,但假设有人试图这样做:
import Prelude hiding (Monad(..))
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
join = (>>= id)
(>>=) :: m a -> (a -> m b) -> m b
a >>= t = join (fmap t a)
(>>) :: m a -> m b -> m b
a >> b = a >>= const b
到目前为止一切都很好,但是当尝试使用 do-notation 时:
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
编译器抱怨:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
问题:< /strong>
do 表示法仅适用于 base:GHC.Base.Monad
吗?有没有办法让它与替代的 Monad 类一起工作?
额外上下文:
我真正想做的是将base:Control.Arrow.Arrow
替换为“通用”Arrow
类:
{-# LANGUAGE TypeFamilies #-}
class Category a => Arrow a where
type Pair a :: * -> * -> *
arr :: (b -> c) -> a b c
first :: a b c -> a (Pair a b d) (Pair a c d)
second :: a b c -> a (Pair a d b) (Pair a d c)
(***) :: a b c -> a b' c' -> a (Pair a b b') (Pair a c c')
(&&&) :: a b c -> a b c' -> a b (Pair a c c')
然后使用Arrow
的 proc-notation 与我的 Arrow
类,但是失败了,就像上面的 do-notation 和 Monad
示例一样。
我将主要使用 Either
作为我的配对类型构造函数,而不是像当前 Arrow
类那样使用 (,)
类型构造函数。这可能会让我的玩具 RTS 游戏(cabal install DefendTheKind
)的代码变得更加漂亮。
The idea that the standard Monad
class is flawed and that it should actually extend Functor
or Pointed
is floating around.
I'm not necessarily claiming that it is the right thing to do, but suppose that one was trying to do it:
import Prelude hiding (Monad(..))
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
join = (>>= id)
(>>=) :: m a -> (a -> m b) -> m b
a >>= t = join (fmap t a)
(>>) :: m a -> m b -> m b
a >> b = a >>= const b
So far so good, but then when trying to use do-notation:
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
The compiler complains:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
Question:
Does do-notation work only for base:GHC.Base.Monad
? Is there a way to make it work with an alternative Monad
class?
Extra context:
What I really want to do is replace base:Control.Arrow.Arrow
with a "generalized" Arrow
class:
{-# LANGUAGE TypeFamilies #-}
class Category a => Arrow a where
type Pair a :: * -> * -> *
arr :: (b -> c) -> a b c
first :: a b c -> a (Pair a b d) (Pair a c d)
second :: a b c -> a (Pair a d b) (Pair a d c)
(***) :: a b c -> a b' c' -> a (Pair a b b') (Pair a c c')
(&&&) :: a b c -> a b c' -> a b (Pair a c c')
And then use the Arrow
's proc-notation with my Arrow
class, but that fails like in the example above of do-notation and Monad
.
I'll use mostly Either
as my pair type constructor and not the (,)
type constructor as with the current Arrow
class. This might allow to make the code of my toy RTS game (cabal install DefendTheKind
) much prettier.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要使用 NoImplicitPrelude 扩展 用于完整的可重新绑定语法,包括
do
和proc
。在这种情况下,您会得到以下信息以及其他信息:您还可以调整对否定、相等、文字值等的一些处理。混淆代码的好方法!
ps -- 如果您要重新绑定
do
语法,sigfpe 所说的“参数化 monad” 非常有趣。同样的想法可以在 Control.Monad.Indexed。是的,尽管类型签名截然不同,但它们确实可以使用可重新绑定的语法!You need to use the NoImplicitPrelude extension for full rebindable syntax, including
do
andproc
. In that case, you get the following, among other stuff:You can also tweak some handling of negation, equality, literal values, and whatnot. Great way to obfuscate code!
p.s. -- If you're going to rebind the
do
syntax, what sigfpe calls "parameterized monads" are great fun. The same idea is available incategory-extras
under Control.Monad.Indexed. And yes, they do work with rebindable syntax, despite the wildly different type signatures!