{- Hi ! I have tried to write an "EnvState" monad transformer, but it is quite useless because when a function peeks at the state but ignores the environment (or vice versa) the code won't compile. GHC tells that the monad I use is no instance of the MonadEnvState, but I really think it is! An example: ( I attach the monad transformer file, MonadTrans2.hs, if someone wonders how EnvStateT looks (I have only written EnvStateT myself, my teacher has written the others some time ago (I think)) ) -} import MonadTrans2 data Env = Env Int data State = State Int type M = EnvStateT Env State IO f, g, h :: M () f = do (Env e, State s) <- getES -- This works since I show GHC return () -- exactly what Env and State I use ? g = do State s <- getS -- compile time error! return () h = do Env e <- getE -- compile time error! return () {- I have already told Haskell that the monad M uses an `Env' and a `State' (the `type M = ...') so why does GHC complain? The function `g' gives: No instance for (MonadEnvState (EnvStateT Env State IO) e State) arising from use of `getS' at envstate.hs:33 In a 'do' expression pattern binding: State x <- getS In the definition of `g': do State x <- getS return () This means that my environment-state monad is nearly useless, since all functions have to use both the state and the environment in order to compile. I thought the following could solve the problem: instance MonadEnvState M Env State since I then tell Haskell that M is an instance of MonadEnvState, but then the code won't compile: Illegal instance declaration for `MonadEnvState M Env State' (The instance type must be of form (T a b c) where T is not a synonym, and a,b,c are distinct type variables) In the instance declaration for `MonadEnvState M Env State' Does anyone know what to do? Is this a problem with Haskell without any solution? Must one perhaps first make a state monad and then transform the state monad into an environment monad? Can't one have both a state and an environment in one single monad at the same time without these compiler errors? Thanks for any help ! Best regards, Magnus Lindberg -}
On Sun, 04 May 2003 20:06:32 +0200 Magnus Lindberg <f98mali@dd.chalmers.se> wrote:
{- Hi ! I have tried to write an "EnvState" monad transformer, but it is quite useless because when a function peeks at the state but ignores the environment (or vice versa) the code won't compile. GHC tells that the monad I use is no instance of the MonadEnvState, but I really think it is! An example: ( I attach the monad transformer file, MonadTrans2.hs, if someone wonders how EnvStateT looks (I have only written EnvStateT myself, my teacher has written the others some time ago (I think)) ) -}
import MonadTrans2
data Env = Env Int data State = State Int
type M = EnvStateT Env State IO
f, g, h :: M ()
f = do (Env e, State s) <- getES -- This works since I show GHC return () -- exactly what Env and State I use ?
g = do State s <- getS -- compile time error! return ()
h = do Env e <- getE -- compile time error! return ()
{- I have already told Haskell that the monad M uses an `Env' and a `State' (the `type M = ...') so why does GHC complain? The function `g' gives:
No instance for (MonadEnvState (EnvStateT Env State IO) e State) arising from use of `getS' at envstate.hs:33 In a 'do' expression pattern binding: State x <- getS In the definition of `g': do State x <- getS return ()
This means that my environment-state monad is nearly useless, since all functions have to use both the state and the environment in order to compile. I thought the following could solve the problem:
instance MonadEnvState M Env State
since I then tell Haskell that M is an instance of MonadEnvState, but then the code won't compile:
Illegal instance declaration for `MonadEnvState M Env State' (The instance type must be of form (T a b c) where T is not a synonym, and a,b,c are distinct type variables) In the instance declaration for `MonadEnvState M Env State'
Does anyone know what to do? Is this a problem with Haskell without any solution? Must one perhaps first make a state monad and then transform the state monad into an environment monad? Can't one have both a state and an environment in one single monad at the same time without these compiler errors?
Thanks for any help !
Best regards, Magnus Lindberg -}
If your instructor gave you the task of writing a monad transformer with environment and state, and (s)he provided you with MonadTrans2.hs, it seems to me that you are meant to use the declarations in it, rather than ignore them and write something from scratch. If the directions were specifically to implement this from scratch, or you weren't given MonadTrans2.hs as part of the exercise, or you are doing this on your own, then you'll need to learn some of the details of the non-standard extension, multiparameter type classes. Your analysis of why getES works is accurate. Your analysis of the use of your monad isn't completely accurate. Your monad is cumbersome, not useless. As it is now, you have to directly or indirectly specify the type for getES (you'll get a similar error with (Env _,_) <- getES, I'm fairly certain), and you have to directly specify the type for getS/E. So, to solve your problem, you can explicitly specify the type of getS/E/ES everytime you use it. It can't be that hard, most statically typed language programmers have been putting up with that for about half a century :D. Okay, that solution is far from ideal. The real solution is functional dependencies. Rather than give you the answer on a silver plate, I'll leave it to you to look up the relevant information and figure out how to apply it to your problem. If you still can't figure it out, then post again, though I expect the timestamp to be at least 18 hours after the timestamp on this message.
participants (2)
-
Derek Elkins -
Magnus Lindberg