用于Clojure中的身份monad

G__*_*G__ 10 monads clojure clojure-contrib

我一直在为Clojure程序员阅读monad优秀介绍.文章说明Identity monad在功能上等同于Clojure的let,而Sequence/List monad等同.

当文章到达monad变换器时,它显示了一个组合Maybe和Sequence monad的示例.好了,一个原因是使用序列单子,而不是针对的是我可以改变它.但是,转换一个Identity monad对我来说没有意义 - 这不总是等同于构建变换monad的任何东西吗?例如,如果我使用Identity转换了Maybe - 那不就是给我一个Maybe,这本来更容易直接声明吗?

有人可以清楚在Clojure中是否有实际用途来选择一个版本monad而不是let(也许我不是一直在考虑变换器的含义?),还是它只是为了理论上的完整性?

小智 8

实际上,身份monad作为monad变换器的基础非常有用.例如,monad变换器(也许-t)允许除了nil之外的任何其他值:

1:2 => (use 'clojure.contrib.monads)
nil
1:3 => (domonad maybe-m [a 1 b 2] (+ a b))
3
1:4 => (domonad maybe-m [a 1 b nil] (+ a b))
nil
;; Domain uses the :fail keyword as the nil value:
1:6 => (domonad (maybe-t identity-m :fail) [a 1 b :fail] (+ a b))
:fail
Run Code Online (Sandbox Code Playgroud)

请注意,使用maybe-m作为基本monad将同时快捷方式:fail和nil,而不仅仅是:fail.


Mic*_*zyk 7

一个很好的理由是你可以编写一个与特定monad无关的monadic函数,然后在一个with-monad块中执行它们.identity-m如果你写的话,你可以选择不涉及任何特殊的monadic伏都教(with-monad identity-m ...).

(显然,如果你的monadic函数必须使用它所使用的monad的某些属性,比如getter的可用性和状态的setter等,这将不起作用.然而,并非所有的monadic函数都是这样的.)