0

私は一般的にMonadsとHaskellに不慣れであり、それらを使用するときに値を返す方法を理解しようとしています。私のコードは次のようになります。

foo :: A -> B
foo a = do  b <- fooC a (C 0)
            -- want to return just (B "b")

fooC :: A -> C -> State MyState B
fooC a c = return (B "b")

を使ってみsnd (snd b)ましたが、どうやらState MyState Bタプルではないのですか?どうすれば希望の値を返すことができます(B "b")か?

編集:ダニエルのアドバイスを考慮に入れると、書き直しは次のようになります。

data MyState = MyState String
data C = C Int
foo :: String -> String
-- want to return just "b"
foo a = evalState (fooC a) (C 0)

fooC :: String -> Int -> State MyState String
fooC a c = return "b"

それでもコンパイルエラーが発生します。

Couldn't match expected type `State s0 String'
            with actual type `Int -> State MyState String'
In the return type of a call of `fooC'
Probable cause: `fooC' is applied to too few arguments
In the first argument of `evalState', namely `(fooC a)'
In the expression: evalState (fooC a) (C 0)

編集2:修正済み!最終バージョンは次のようになります。

import Control.Monad.State
data MyState = MyState String
data C = C Int
foo :: String -> String
-- want to return just (B "b")
foo a = evalState (fooC a (C 0)) (MyState "whatever")

fooC :: String -> C -> State MyState String
fooC a c = return "b"

main = print(foo("test"))
-- prints "b"
4

1 に答える 1

6

必要なのは

foo a = evalState (fooC a (C 0)) (MyState "whatever")

State MyState Bアクションを作成しfooC a (C 0)、ラップを解除して関数を取得し、その関数を初期状態に適用します。この例では状態が使用されていないため、ここではundefinedの代わりに使用することもできますMyState "whatever"が、一般に、意味のある初期状態を指定する必要があります。

State MyState Bタプルではなく、関数と同型です

MyState -> (B, MyState)

ただし、その関数はnewtype(モナド変換子ライブラリのパッケージとバージョンによって詳細が異なります)ラップされているため、初期状態に適用された関数の結果にアクセスするには、ラップ解除関数が必要です。のためStateに、があります

runState :: State s r -> (s -> (r,s))

これにより、ペアを返す関数が得られます。

evalState :: State s r -> (s -> r)

これにより、で構成される関数が得られるfstため、最終状態は破棄され、

execState :: State s r -> (s -> s)

これは関数をで構成するsndため、最終状態のみが返されます。

于 2012-11-22T16:09:45.993 に答える