1

私の理解では、do モナドの場合、各ステップには継続と終了があります。

この著者は次のように書いています

純粋性、強力な型、およびモナドが次のことができることを確認しました。

...

  • 実行のさまざまなフェーズ間の混乱から生じる可能性のあるバグを防ぎます。

私の質問は:モナドが防ぐバグのカテゴリは何ですか?

4

2 に答える 2

0

効果の分離

通常の型がデータを区別する方法を提供するように、モナドは結果を区別する方法を提供します

エリクサー

Elixirこれは、Erlang 上のほぼ純粋な関数型言語であるの例です。この例は、私の仕事で頻繁に発生する実際の状況から派生したものです。

def handle_call(:get_config_foo, _, state) do:
  {:reply, state.foo, state}
end

def handle_call(:get_bar, _, state) do:
  {:reply, state.bar, state}
end

def handle_call({:set_bar, bar}, _, state) do:
  {:reply, :ok, %{state | bar: bar}}
end

これはGenServerの API を定義します。これは、いくつかを保持stateし、クエリや変更を可能にする小さな Erlang ノードです。最初の呼び出しは、不変の構成設定:get_config_fooを読み取ります。呼び出しの 2 番目のセットおよびは、変更可能な状態変数を取得および設定します。:get_bar{:set_bar, bar}

次のバグを防ぐために、ここにモナドがあればいいのにと思います。

def handle_call({:set_bar, bar}, _, state) do:
  {:reply, :ok, %{state | foo: bar}}
end

あなたは間違いを見つけることができますか?さて、readonly 値を書きました。Elixir にはこれを妨げるものは何もありません。GenServer 状態の一部を読み取り専用としてマークし、他の部分を読み取り/書き込みとしてマークすることはできません。

Haskell: リーダーと状態

Haskell では、さまざまな種類の効果を指定するためにさまざまなモナドを使用できます。読み取り専用状態 ( Reader) と読み取り/書き込み状態は次のとおりです。

data Reader r a = Reader (r -> a)
data State s a = State (s -> (a, s))

Reader設定状態にアクセスしてr何らかの値を返すことができますaState状態を読み取り、何らかの値返し、状態を変更することができます。どちらもモナドであり、基本的には、これらの状態アクセスを命令型の方法で順番に連鎖できることを意味します。ではReader、最初に 1 つの構成設定を読み取り、次に (その最初の設定に基づいて) 別の設定を読み取ることができます。ではState、状態を読み取り、(読み取った内容に基づいて) さらに変更することができます。ただし、実行中に状態を変更することはできません。Reader

決定論的効果

これを繰り返させてください。いくつかの呼び出しをバインドすると、その間にリーダーの状態を変更Readerできないことが保証されます。getConfigFoo1 :: Reader Config Foo1と がありgetConfigFoo2 :: Foo1 -> Reader Config Foo2、 がある場合、両方のクエリが同じ で実行されるgetAllConfig = getConfigFoo1 >>= getConfigFoo2ことが確実Configです。Elixir にはこの機能がなく、上記のバグが見過ごされてしまいます。

これが役立つその他の効果は、(Writerロギングなどの書き込み専用状態) とEither(例外処理) です。またはWriterの代わりにある場合、状態が常に追加されるだけであることを確認できます。があれば、発生する可能性のある例外の種類を正確に把握できます。これは、ロギングと例外処理に使用するよりもはるかに優れています。ReaderStateEitherIO

于 2019-02-25T14:44:54.147 に答える