2012-09-08 25 views
0

我需要編寫一個'序列,也許m'(monad結合序列monad的行爲與可能monad)的幫助。寫一個序列 - 也許monad使用clojure.algo.monads

該規則應當是:

  • 如果任何輸入是零,那麼整個表達失敗。
  • 否則,就像序列單子會做的那樣評估身體。
 
    (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 <...> 
     ]) 

其中< ...>的功能。

回答

5
; 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 

的唯一一點確實值得密切關注着這裏是在m-bind第二nil-or-has-nil?。第一個是預期的 - 通過一個monadic值,m-bind必須確定它是否爲nil -ish,並應立即導致nil。第二個檢查計算結果 - 如果失敗(產生任何nil),則總體結果必須是nil(而不是由(apply concat [nil nil ...])產生的空列表)。

+0

輝煌。謝謝! – zcaudate

3

domonad的輸出必須是單值,在sequence-m的情況下,這意味着它必須是一個序列。要求輸出nil打破這一點,你沒有monad。

你可能正在尋找的是直接使用monadic變換器添加「maybe」到序列monad,很容易做到,並在這裏描述:http://clojuredocs.org/clojure_contrib/1.2.0/clojure.contrib.monads/maybe-t

你會想要寫

(def sequence-maybe-m (maybe-t sequence-m)) 

其中maybe-t增加了「可能」的序列單子。使用這將使

(domonad sequence-maybe-m [a [1 2 3] b [1 nil 3]] (+ a b)) 

產量

(2 nil 4 3 nil 5 4 nil 6) 

這是這種類型的單子有效輸出。如果您需要取消其中包含nil的結果,只需在單元的輸出上使用some nil?來檢查它們。

綁定nilb,你在你的例子

(domonad sequence-maybe-m [a [1 2 3] b nil] (+ a b)) 

要求沒有任何意義,因爲相關nil是不是一個序列。在轉換後的monad中,返回值將是空列表()。將[nil]綁定到b會更合適,那麼您將獲得(nil nil nil)

它有助於記住,單子用於組成相同的簽名功能和本身可以是這樣的組合物的一部分,因此它們必須產生一元值(在這種情況下,序列)自己和他們的身體的任何結合絕也有一個monadic價值。