3

こんにちは、私は Haskell 初心者で、主にLYAHHuttonを読んでいます。最近、State モナドの Functor インスタンスが次のように表現されているこのスニペットに出くわしました。

instance Functor (State st) where
    fmap f m = State $ \st -> let (a, s) = runState m st in (f a, s)

これは次のように削減できます。

instance Functor (State st) where 
    fmap f m = State $ (\(a,s) -> (f a,s)) . runState m

この削減の背後にあるワークフローを説明できる人はいますか?

また、そのような削減技術を学ぶ方法についての良いリソース/アドバイスは何ですか?

4

1 に答える 1

9

私が取り上げた概念 (ラムダ関数など) のいずれかが不明確な場合は、LYAH でそれらについて読み、 で少し遊んでくださいghci。その後、この返信にもう一度戻ってきてください。すべてが少し解決するはずです。

他のプログラミング言語から来ている場合に混乱するかもしれないことの 1 つは、Haskell では次のような関数を使用できることです。

runState

1つの引数を追加します

runState m

そしてそれはまだ有効な機能です。次に、2 番目の引数を追加すると、次のようになります。

runState m st

最終的に値を計算します。これはrunState、 が 2 つの引数の関数である場合、runState mは 1 つの引数の関数であり、1 つの引数の他の関数と同じように扱うことができることを意味します。


あなたの例で重要な部分は

\st -> let (a, s) = runState m st in (f a, s)

これはに変えることができます

(\(a,s) -> (f a,s)) . runState m

関数合成に演算子を使用して、(.).


それがどのように可能であるかを理解するための最初のステップは、let…in式をラムダ形式で書き直すことができることを認識することです。この意味は

let y = f x in expr

次のように書くことができます

(\y -> expr) (f x)

これらの行は両方とも、名前yを の値にバインドします。式f xに必要なのはこれだけです。let…in

その知識を応用すると

\st -> let (a, s) = runState m st in (f a, s)

のように書き換えられることがわかります。

\st -> (\(a, s) -> (f a, s)) (runState m st)

途中まで来ました!


関数構成の定義は次のとおりです。

f . g = \x -> f (g x)

これは、何かを持っているときはいつでも\x -> f (g x)f . g.

さて、この場合、そのように見えるものがあります!そう言えば

f = \(a, s) -> (f a, s)
g = runState m
x = st

私たちはそれを見る

\st -> (\(a, s) -> (f a, s)) (runState m st)
\x  -> f                     (g          x)

関数合成が起こるのを待っているだけです。だから私たちはそれをに変えることができます

f . g

これは、 と の定義によりfg

f                     . g
(\(a, s) -> (f a, s)) . (runState m)

の周りの括弧を削除することができますrunState m

于 2013-11-04T11:57:30.020 に答える