0

'sequence-maybe-m' (sequence モナドの振る舞いと Maybe モナドを組み合わせたモナド) を書くのに助けが必要です。

ルールは次のとおりです。

  • 入力のいずれかが nil の場合、式全体が失敗します。
  • それ以外の場合は、シーケンス モナドが行うように本体を評価します。
    (ドモナド シーケンス-多分-m [a [1 2 3] b [1 2 3]] (+ ab))
        ;; => (2 3 4 3 4 5 4 5 6)

    (domonad sequence-maybe-m [a [1 2 3] b nil] (+ ab))
        ;; =>なし

    (domonad sequence-maybe-m [a [1 2 3] b (範囲 a)] (+ ab))
        ;; => (1 2 3 3 4 5) 「for」と同じ

    (domonad sequence-maybe-m [a [1 2 3] b [1 nil 3]] (+ ab))
        ;; =>なし

clojure.algo.monads ライブラリと互換性がある場合はボーナスになります。

(defmonad sequence-maybe-m
     [m-result <...>
      m-bind   <...>
      m-zero   <...>
      m-plus   <...>
      ])

<...> は関数です。

4

2 に答える 2

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

ここで注目すべき唯一の点は、 の 2 番目nil-or-has-nil?の部分m-bindです。1つ目は予想されます - モナド値が渡され、それが-ish であるm-bindかどうかを判断する必要があり、すぐに. 2 番目は、計算の結果をチェックします。計算が失敗した場合 (何らかの が生成された場合)、全体的な結果は次のようになります(たとえば、 の結果の空のリストとは対照的です)。nilnilnilnil(apply concat [nil nil ...])

于 2012-09-08T20:37:36.370 に答える
3

の出力はdomonadモナド値でなければなりません。その場合、sequence-mそれはシーケンスでなければなりません。ブレークの出力を要求するnilと、モナドがありません。

あなたがおそらく探しているのは、モナドトランスフォーマーを使用してシーケンスモナドに「たぶん」を直接追加することです。これは非常に簡単で、ここで説明されています: 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?

あなたの例であなたが求めるようにバインドnilするb

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

nilはシーケンスではないため、どちらも意味がありません。変換されたモナドでは、戻り値は空の​​リストになります()[nil]にバインドする方が適切bです(nil nil nil)

モナドは同じ署名の関数を構成するために使用され、それ自体がそのような構成の一部になる可能性があることを覚えておくと役立ちます。したがって、モナド値 (この場合はシーケンス) 自体を生成する必要があり、その本体では結合もモナド値。

于 2012-11-01T21:19:36.247 に答える