我偶尔会在代码中遇到类似于 monad 但
没有在 >>=
中保持一致的类型.
这是我能想到的最简单的例子:
(首先是一些类型级别的 bool 值:
data TyT = TyT
data TyF = TyF
class TyOr a b c | a b -> c
instance TyOr TyF TyF TyF
-- rest similarly
)
现在这是我们的“monad”类型构造函数:
data Marked p a = Marked a
deriving (Show)
对于给定的
p
, Marked p
是 * -> *
其行为非常类似于 m
在一个monad,但不同的是,当我们定义“绑定(bind)”时,接下来会发生:
(>>%) :: (TyOr p q r) => Marked p a -> (a -> Marked q b) -> Marked r b
(Marked x) >>% f = Marked y where Marked y = f x
这里不同的是
>>%
的结果有不同的类型构造函数比参数。除此之外,它基本上是一个单子(monad)。
我们可以这样使用它:
a :: Marked TyF Int
a = Marked 5
f :: Int -> Marked TyT Int
f x = Marked (x + 1)
ghci> a >>% f
Marked 6
ghci> :t a >>% f
a >>% f :: Marked TyT Int
(这受到 outis's observation that Python's "with" can't be a monad because it changes the type 的启发,但我以其他(更简单)的方式看到它
也)。
最佳答案
嗯,它在某种意义上与 monad 密切相关,只是与 Monad
不兼容。类型类。特别是,我们可以注意到以下相似之处:
mappend :: a -> a -> a
和 mempty :: a
. join :: m (m a) -> m a
和 return :: a -> m a
. (.) :: arr b c -> arr a b -> arr a c
和 id :: arr a a
. ...那么一个单子(monad)会是什么
join
是按类型索引的吗?嗯。您可能会发现一些有趣的引用资料,探索相关概念:
发布脚本-您在对该问题的评论中说:
You're right. I actually want to fix that to be more monad-like though, even though I'm not really "using" monads. I'll edit it. Though I would have more or less the same question about Applicatives.
实际上,将事情限制在
Applicative
变化很重要! a -> Marked p b
之间的区别和 Marked p (a -> b)
是,在前者中,Marked p
的属性结构可以依赖于 a
范围;而在后者中,标记与函数的参数无关。独立意味着两者可以分开处理,大大简化了事情;注意 a
类型的任何值与 () -> a
类型的函数同构,你可以把它变成某种两层版本的Arrow
以直截了当的方式。另一方面,涉及
Monad
意味着函数和标记上下文之间存在某种程度的交错,这使事情变得复杂,原因类似于 discussed in the answers to this question .
关于design-patterns - 这种类似 monad 的函数式编程模式叫什么名字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7135540/