0

When I do:

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

with simple.hs containing:

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

my computer runs out of memory.

How can I successfully make the Measure monad an instance of MonadState (i.e. have test above return 1)? The Measure type is already an instance of Monad with bind and return defined. Is there some default way I can define MonadState's put and get in terms of lift, bind, and return to make it work? I tried:

get = lift   get
put = lift . put

but I couldn't get the (transformer?) types to work out:

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
cronburg
  • 892
  • 1
  • 8
  • 24

2 Answers2

3

Measure is already defined in a following way:

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

You can see that there is no place to store your Int, so you cannot make it a proper instance of MonadState. If you want to extend Measure to MonadState, you can use StateT monad transformer:

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

What happened here? StateT s is a monad transformer, which lets you to combine State s monad with any other monad (in this example Measure)

Michal Seweryn
  • 363
  • 2
  • 8
  • I think I need the opposite stack order - something like `test :: Measure (State Int ())`, since I want to do `sample :: Measure a -> [] -> IO [(a,P)]` on the return value of `test`. Trying this out now... Thanks for the quick response! – cronburg Dec 04 '14 at 20:32
  • 2
    @KarlC the StateT monad does internally "reverse orders"; all monad transformers do. For example, `MaybeT` is defined as: `newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}`, so `MaybeT IO ()` is the type of an I/O program which, if it completes, will either contain `Nothing` or else `Just ()`. Similarly, `StateT` is defined as `newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}`, so once you `runStateT test startState` you will have a `Measure (Int, Int)` instance. – CR Drost Dec 04 '14 at 20:51
  • The `test :: StateT Int Measure Int` is doing the trick for me now, along with `runStateT` to get a `Measure (Int,Int)` out. Still trying to wrap my head around what is specific to the `MaybeT` and `StateT` examples from the online Haskell wiki, and what can be generalized to other monads... – cronburg Dec 04 '14 at 21:15
0

The exact code which ended up working for me is:

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) []
cronburg
  • 892
  • 1
  • 8
  • 24