我需要帮助写一个'sequence-maybe-m'(一个monad,它结合了一个序列monad和一个monad的行为).
规则应该是:
(domonad sequence-maybe-m [a [1 2 3] b [1 2 3]] (+ a b))
;; => (2 3 4 3 4 5 4 5 6)
(domonad sequence-maybe-m [a [1 2 3] b nil] (+ a b))
;; => nil
(domonad sequence-maybe-m [a [1 2 3] b (range a)] (+ a b))
;; => (1 2 3 3 4 5) same as 'for'
(domonad sequence-maybe-m [a [1 2 3] b [1 nil 3]] (+ a b))
;; => nil
如果它与clojure.algo.monads库兼容,那将是一个奖励:
(defmonad sequence-maybe-m
[m-result <...>
m-bind <...>
m-zero <...>
m-plus <...>
])
Run Code Online (Sandbox Code Playgroud)
其中<...>是函数.
; helper function for nil-ness
(defn nil-or-has-nil? [xs] (or (nil? xs) (some nil? xs)))
; the actual monad
(defmonad sequence-maybe-m
[m-result (fn [v] [v]) ; lift any value into a sequence
m-bind (fn [mv f] ; given a monadic value and a function
(if (nil-or-has-nil? mv) ; if any nil,
nil ; result in nil
(let [result (map f mv)] ; map over valid input seq
(if (some nil? result) ; if any nils result
nil ; return nil
(apply concat result))))) ; else flatten resulting seq
m-plus (fn [& mvs] ; given a sequence of mvs
(if (some nil-or-has-nil? mvs) ; if any nil,
nil ; result in nil
(apply concat mvs))) ; otherwise, join seqs
m-zero []]) ; empty seq is identity for concatenation
Run Code Online (Sandbox Code Playgroud)
唯一的一点确实值得密切关注着这里是第二个nil-or-has-nil?中m-bind.第一个是预期的 - 通过一个monadic值,m-bind必须确定它是否是nil-ish并且应该立即产生nil.第二个检查计算的结果 - 如果它失败(产生任何nil),那么整个结果必须是nil(而不是,例如,由此产生的空列表(apply concat [nil nil ...])).
| 归档时间: |
|
| 查看次数: |
420 次 |
| 最近记录: |