nebffa
nebffa

Reputation: 1549

Rigid type error combined with IO and polymorphic types

I am writing an interpreter for a simple language as a project at university, and there is an option to write in some debugging functionality. I thought this would be simple but after taking a break of about a week due to frustration I have come back to deal with this.

The entire haskell file is about 250 lines so I don't want to post the whole thing, but if I haven't given enough information please let me know.

I have this function

interpret_statement :: Prog -> (Var -> Val -> Vars -> o) -> Vars -> Stmt -> o

where (Var -> Val -> Vars -> o) is a debugging function - one of 2 possibilities that I choose

pure_passthrough :: Var -> Val -> Vars -> Vars -- does no IO
write_debugging_info :: Var -> Val -> Vars -> IO Vars -- does IO

I also have another function

interpret_function :: Prog -> (Var -> Val -> Vars -> o) -> Vars -> [Stmt] -> Val

which contains a line

interpret_function prog debug_function vars (x:xs) = interpret_function prog debug_function (interpret_statement prog debug_function vars x) xs 

and is one of 3 lines that gives me a rigid type error saying that

Expected type: Var -> Val -> Vars -> Vars
Actual type: Var -> Val -> Vars -> o

Everything was working completely fine before trying to introduce IO. I have done it this way due to the answer of a separate question on this site that suggested I use a polymorphic function to tell the program whether to do IO or not at run-time depending on whether I receive a command line argument or not.

But now it causes problems because I have a couple of co-dependent functions that I now need to pass polymorphic variables to and from? Oh the humanity! I really think I'm getting better at Haskell guys but this one has me COMPLETELY stumped. How is the "Actualy type" Var -> Val -> Vars -> o which is polymorphic and not really specific?

Note: If I need to include more information PLEASE let me know - I have started with as little as possible so I don't overload people with unnecessary information

Upvotes: 1

Views: 152

Answers (1)

mpartel
mpartel

Reputation: 4492

The call (interpret_statement prog debug_function vars x) is in a position where it must return Vars, it cannot return the type o.

In interpret_function, the return type does not depend on o, so even if you pass in a debug function that returns an IO monad, the result of interpret_function is not an IO monad.

My Haskell is a bit rusty, but I believe you could change interpret_function so that its type becomes

interpret_function :: (Monad m) => Prog -> (Var -> Val -> Vars -> m Vars) -> Vars -> [Stmt] -> m Val

where m will be either IO or some trivial monad (perhaps this one).

Now the implementation of that particular case would go something like this:

interpret_function prog debug_function vars (x:xs) =
  do vars' <- interpret_statement prog debug_function vars x
     return $ interpret_function prog debug_function vars' xs

Upvotes: 4

Related Questions