2017-04-24 65 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不带任何参数:

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

也不对s

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

我们可以结合这些状态的计算与>>,因为任何MonadState s m也是Monad

setAndGet = s >> get 

而且我们可以看看setAndGet的结果runState

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

状态monad中的状态就像underground river,它遵循计算的表面路径。当你不需要它的时候它隐藏了状态,并且让你专注于组成构成计算的(一元)函数。

get就像是一口进入那条河流的水井,让你在需要的时候能够进入公开状态。这是“你所遵循的路径的一部分”,可以这么说,而不是你适用于一元行为的一些外部功能。