Hugh Perkins wrote:
That works just fine as long as the only thing eval has to cope with is print statements (so eval has type IO ()), but I'm guessing the clean solution is to thread a Map.Map through that somehow?

You could do that but your code starts to become messy and you'll hit other limitations. The standard approach to this problem is to use a State monad. Since you are already using one monad, IO, you can can stack the monads using Monad transformers which makes them both available (although you will need to use liftIO, see below)

import Control.Monad
import Control.Monad.State
import Data.Map

type Env = Map String String
type InterpM = StateT Env IO
eval :: a -> InterpM t

instance Eval Print where
  eval (Print value) = liftIO $ putStrLn value

You access and store the state using get and put. For example:

eval (Variable s) = do
                                   s <- get
                                   lookup the value and return it.

There is a paper on using Monads with interpreters (http://web.cecs.pdx.edu/~mpj/pubs/modinterp.html) and an example described at http://www.haskell.org/haskellwiki/Libraries_and_tools/HJS.

Mark
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to