自定义MonadState实例

时间:2014-12-04 19:28:19

标签: haskell monads monad-transformers state-monad

当我这样做时:

cabal sandbox init
cabal update
cabal install hakaru
cabal repl
λ> :l simple.hs 
λ> sample test []

simple.hs包含:

{-# LANGUAGE MultiParamTypeClasses #-}
import Language.Hakaru.ImportanceSampler
import Control.Monad.State
instance MonadState Int Measure
test :: Measure Int
test = put 1 >> get >>= \i -> return i

我的电脑内存不足。

如何成功使Measure monad成为MonadState的实例(即test以上返回1)? Measure类型已经是Monad的实例,其中bindreturn已定义。是否有一些默认方式我可以用MonadStateputget来定义lift' s bindreturn使它工作?我试过了:

get = lift   get
put = lift . put

但是我无法解决(变压器?)类型:

simple.hs:6:9:
    Couldn't match type ‘t0 m0’ with ‘Measure’
    Expected type: Measure Int
      Actual type: t0 m0 Int
    In the expression: lift get
    In an equation for ‘get’: get = lift get

simple.hs:7:9:
    Couldn't match type ‘t1 m1’ with ‘Measure’
    Expected type: m1 () -> Measure ()
      Actual type: m1 () -> t1 m1 ()
    In the first argument of ‘(.)’, namely ‘lift’
    In the expression: lift . put

2 个答案:

答案 0 :(得分:3)

Measure已按以下方式定义:

newtype Measure a = Measure { unMeasure :: [Cond] -> Sampler (a, [Cond]) }

您可以看到没有地方存储您的Int,因此您无法将其设为MonadState的正确实例。 如果您想将Measure扩展为MonadState,可以使用StateT monad transformer:

test :: StateT Int Measure Int
test = put 1 >> get >>= \i -> return i

这里发生了什么? StateT s是一个monad转换器,可让您将State s monad与任何其他monad组合在一起(在此示例中为Measure

答案 1 :(得分:0)

最终为我工作的确切代码是:

import Language.Hakaru.ImportanceSampler
import Language.Hakaru.Distribution
import Control.Monad.State
import System.IO.Unsafe (unsafePerformIO)

test1 :: StateT Int Measure Int 
test1 = do
  i <- lift $ unconditioned $ categorical [(0,0.25), (1,0.25), (2,0.5)]
  j <- lift $ unconditioned $ categorical [(i,0.25), (1,0.25), (2,0.5)]
  put (i + j)
  k <- get 
  return k

run_test1 = unsafePerformIO $ empiricalMeasure 10 (evalStateT test1 0) []