2017-04-24 5 views
0

考える:理解州モナドの `GET`

*Main> let s = state $ \x -> ("foo", x) 
*Main> :t s 
s :: MonadState s m => m [Char] 

を私はget sを呼び出そうとしましたが、以下のコンパイル時にエラーました:

その後
*Main> :t get 
get :: MonadState s m => m s 

*Main> let x = get s 

<interactive>:95:5: error: 
    • Non type-variable argument 
     in the constraint: MonadState t ((->) (m [Char])) 
     (Use FlexibleContexts to permit this) 
    • When checking the inferred type 
     x :: forall s (m :: * -> *) t. 
      (MonadState s m, MonadState t ((->) (m [Char]))) => 
      t 

を、私は、その拡張子を追加しました:

*Main> :set -XFlexibleContexts 

しかし、まだコンパイルされません:

*Main> let result = get s 

<interactive>:9:5: error: 
    • Could not deduce (MonadState s0 m0) 
     from the context: (MonadState s m, MonadState t ((->) (m [Char]))) 
     bound by the inferred type for ‘result’: 
        (MonadState s m, MonadState t ((->) (m [Char]))) => t 
     at <interactive>:9:5-18 
     The type variables ‘s0’, ‘m0’ are ambiguous 
    • In the ambiguity check for the inferred type for ‘result’ 
     To defer the ambiguity check to use sites, enable AllowAmbiguousTypes 
     When checking the inferred type 
     result :: forall s (m :: * -> *) t. 
        (MonadState s m, MonadState t ((->) (m [Char]))) => 
        t 

なぜコンパイルされていないのか説明してください。

答えて

5

矢印をよく見てください。

get :: MonadState s m => m s 
--  ^^^^^^^^^^^^^^ 
--  constraint, not type 

どちら行いsgetは任意の引数を取りません

s :: MonadState s m => m [Char] 
-- ^^^^^^^^^^^^^^ 
-- constraint, not type 

任意のMonadState s mMonadあるので、私たちは、>>でそれらのステートフルな計算を組み合わせることができます。

setAndGet = s >> get 

そして、 setAndGetの結果をと見てみることができます3210:状態モナドで

ghci> runState setAndGet "example" 
("example","example") 
0

状態は、計算の表向きの経路をたどるunderground riverようなものです。あなたがそれを必要としないときに状態を隠し、計算を構成する(モナド)関数の作成に集中することができます。

getは、その川を叩く井戸のようなもので、必要なときに州を開いた状態にすることができます。それはあなたがモナドの行動に適用するいくつかの外部機能ではなく、話すために「従う道の一部」です。

関連する問題