【发布时间】:2011-10-31 10:07:42
【问题描述】:
我偶尔会在代码中遇到类似于 monad 但
不会在 >>= 中保持一致的类型。
这是我能想到的最简单的例子:
(首先是一些类型级别的布尔值:
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,但不同,接下来会出现,当我们定义“绑定”时:
(>>%) :: (TyOr p q r) => Marked p a -> (a -> Marked q b) -> Marked r b
(Marked x) >>% f = Marked y where Marked y = f x
这里不同的是>>%的结果类型不同
构造函数比参数。除此之外,它基本上是一个单子。
我们可以这样使用它:
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 的启发,但我以其他(更简单)的方式看到它 也)。
【问题讨论】:
-
(>>%)的类型签名看起来更接近flip (<*>) :: Applicative f => f a -> (f a -> f b) -> f b而不是(>>=) :: Monad m => m a -> (a -> m b) -> m b,所以我会说这更像是应用程序而不是单子。 -
你是对的。我实际上想将其修复为更像单子,即使我并不是真正“使用”单子。我会编辑它。虽然我对 Applicatives 有或多或少相同的问题。
-
Google 搜索“Indexed Monad”、“Monadish”或“Monadic Region”。
标签: design-patterns haskell functional-programming monads