这个类似monad的函数式编程模式的名称是什么?

时间:2011-08-21 00:16:27

标签: design-patterns haskell functional-programming monads

我偶尔在代码中遇到一个类似于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)

对于给定的pMarked 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

这里有什么不同,>>%的结果有不同的类型 构造函数比参数。除此之外,它基本上是一个单子。

我们可以像这样使用它:

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的启发,但我已经以其他(更简单的)方式看到了它 太)。

1 个答案:

答案 0 :(得分:10)

嗯,它在某种意义上与monad密切相关,只与Monad类型类不兼容。特别是,我们可以注意到以下几点:

  • Monoids具有关联操作,其标识在一致类型的值上定义:mappend :: a -> a -> amempty :: a

  • Monads具有在类型构造函数上定义的标识的关联操作,例如:join :: m (m a) -> m areturn :: a -> m a

  • 函数 - 实际上,类别中的箭头 - 具有关联操作和标识,但关联操作是由类别的对象索引的,这里的意思是“类型” :(.) :: arr b c -> arr a b -> arr a cid :: arr a a

...那么join被类型编入索引的monad是什么? HM。

您可能会发现一些有趣的参考资料,探索相关概念:


post scriptum - 你在对这个问题的评论中说了这个:

  你是对的。我实际上想要修复它更像monad,尽管我不是真的“使用”monad。我会编辑它。虽然我或多或少会有关于Applicatives的相同问题。

实际上,将内容限制为Applicative更改非常重要! a -> Marked p bMarked p (a -> b)之间的区别在于,在前者中,Marked p结构的属性可能取决于a参数;而在后者中,标记与函数的参数无关。独立性意味着两者可以分开处理,这大大简化了事情;注意a类型的任何值与() -> a类型的函数同构,您可以直接将其转换为Arrow的某种双层版本。

另一方面,涉及Monad意味着函数和标记上下文之间存在某种程度的交错,这使得问题变得复杂,原因与discussed in the answers to this question类似。