7

When learning about new programming subjects I usually follow a pattern: I read about it, I understand it, and then I code up a few examples to make sure I really get it.

I've read a lot about monads, and I'm confident that I understand and get them. I'm now at a stage where I'd really like to code up a few monads to solidify my understanding, and really figure out what it takes to implement bind for a variety of types.

The problem is that I can't think of many obvious monads to implement, so I'm looking for recommendations. Preferably, I'd like a list of recommendations, with some easy ones and some not so easy ones.

I also realize that while monads are used to 'encapsulate' side effects in functional programs, they are also more general than that. So, I'd like the recommendations to include monads that both encapsulate side effects and some general ones.

Thanks!

(as a side note: I'll be working with f# to do this, but I think this question could apply to any functional language).

4

3 回答 3

5

我认为All About Monads中的目录是一个好的开始(continuation monad 实际上对变态很有用,请参见此处的示例);另外还有解析器,可能还有事务效果异步是另一种尝试自己实现的好方法(逻辑上单线程代码,在不同的实际线程之间跳跃以实现非阻塞)。反应式框架的底层 monad看起来像是一个很好的高级挑战。

于 2009-10-03T22:46:53.543 回答
2

遵循某种一元法则的数据结构/计算列表非常丰富。

它从可选数据列表('a option在 F# 中)、延续和多线程到解析器等高度复杂的事物。

只需开始实施其中的一些。基础练习:

// Identity monad

let something = ident {
    let! value = id 42
    return value
}

let somethingelse = ident {
    let! value = something
    let! otherValues = id 40
    return value + othervalue
}


// Implement maybe for 'a option
let sum = maybe {
    let! a = maybeInputNumber("a")
    let! b = maybeInputNumber("b")
    let! c = maybeInputNumber("c")
    return a + b + c
}

match sum with
| None -> ...
| Some(n) -> ...

您还可以通过使用一些辅助函数和显式的单子语法来增加您的理解。

// Given m >>= f for m.Bind(f)

let (>-) f monad = monad >>= (fun k -> return(f x))

// What's this?
let res = ((+) 1) >- [1..10]

如果您想要一些复杂的示例,请查看monadic parser combinators。这将允许您在普通 F# 中实现复杂的递归下降解析器(查看FParsec -Project)

let parseVector = parser {
    do! ignore $ char '('
    let! [x;y;z] = sepBy parseNumber "," 
    do! ignore $ char ')'
    return new Vector(x, y, z)
}

一个简单的实现基于以下类型:

type 't Computation = 
    | Error of ...
    | Result of 't

type Input     = char list
type 'a Parser = Input -> (('a * Input) Computation)

尝试实现绑定返回;-)

作为一般提示:如果你真的想在自然环境中理解 monad,你将不得不使用 Haskell ;-) 在 F# 中只有计算表达式,只是一个模糊的类比,但 Haskell 为任何 monadic 引入了一个通用接口计算。非常适合尝试它们!

于 2009-10-03T16:35:43.267 回答
1

虽然我认为 Haskell 是学习 monad 的自然语言这一事实​​没有什么挑战,但我发现一个非常有用的练习是将 monadic 计算引入一种没有开箱即用的类似 Haskell 的超级语言为他们提供顺畅的支持。这在任何语言中都是完全可能的,并且在任何相当高级的语言中,都可能具有创造性并实际上使它们看起来不错——在这个过程中学到了很多东西!例如,我已经看到了很酷的 Python 单子语法(我认为是在Valued Lessons中)。

还有 Clojure 的 clojure.contrib.monads 库,它为在 Lisp 中使用 monad 提供了很好的工具。尝试在功能上重新创建它的一些功能可能很有启发性。此外,有时使用它代替 Haskell 可能有助于将一般模式与 Haskell 语法的细节分开(尽管它们非常好,可以肯定)。

于 2009-12-19T05:05:58.540 回答