2014-12-04 56 views
0

當我這樣做:定製MonadState例如

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單元成爲MonadState的實例(即test的返回值高於1)? Measure類型已經是Monad的一個實例,其中bindreturn已定義。是否有一些默認方式可以根據liftbindreturn來定義MonadStateputget以使其正常工作?我想:

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 

回答

3

Measure以下列方式已經被定義:

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

你可以看到沒有地方存儲您的Int,因此您無法將其設置爲MonadState的適當實例。 如果要擴展到MeasureMonadState,您可以使用StateT單子轉換:

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

這裏發生了什麼? StateT s是一個單子轉換,它可以讓你State s單子與任何其他單子結合(在這個例子中Measure

+0

我想我需要相反的堆棧順序 - 類似'test :: Measure(State Int())',因爲我想在''返回值''上做'sample :: Measure a - > [] - > IO [(a,P) test'。 現在就試試這個......感謝您的快速響應! – KarlC 2014-12-04 20:32:57

+2

@KarlC StateT monad在內部執行「反向命令」;所有monad變壓器都這樣做。例如,'MaybeT'定義爲:'newtype MaybeT ma = MaybeT {runMaybeT :: m(Maybe a)}',所以'MaybeT IO()'是I/O程序的類型,如果它完成了,將包含'Nothing'或者'Just()'。同樣,'StateT'被定義爲'newtype StateT sma = StateT {runStateT :: s - > m(a,s)}',所以一旦你運行了測試startState,你就會有一個Measure(Int,Int)實例。 – 2014-12-04 20:51:59

+0

'test :: StateT Int Measure Int'現在正在爲我執行這個技巧,以及'runStateT'來獲取'Measure(Int,Int)'。仍然試圖圍繞着Haskell在線wiki的'MaybeT'和'StateT'示例的具體內容,以及可以推廣到其他monad的內容...... – KarlC 2014-12-04 21:15:29

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) []