title: Unwrapping the Haskell State Monad
body: <p>In the process of writing an assignment for university I am having the ever-joyous fun of learning new Haskell monads. Yay!!!</p>
  
  <p>I have a function that typechecks just fine:</p>
  
  <pre><code>compile :: Prog -&gt; State VarsState String
  compile prog@(Prog functions) = do
      s1 &lt;- sequence (map (translate_func 0) [get_function prog name | name &lt;- [func_name func | func &lt;- functions]])
      return $ trace ("here's the program: \n" ++ show prog) $ concat $ s1
  </code></pre>
  
  <p>but when this other function:</p>
  
  <pre><code>maybe_compile_prog ::
      MaybeOK Prog -&gt; String -&gt; IO ()
  maybe_compile_prog (Error msg) _ = do
      putStrLn ("error: " ++ msg)
  maybe_compile_prog (OK prog) modulename = do
      s1 &lt;- compile prog
      writeFile (modulename ++ ".m") ((header modulename) ++ s1)
  </code></pre>
  
  <p>tries to call it, it blows up at the line</p>
  
  <pre><code>s1 &lt;- compile prog
  </code></pre>
  
  <p>saying it couldn't match the expected type "IO t0" with actual type "State VarsState String".</p>
  
  <p>I assume this is because maybe_compile_prog returns type IO () so it expects to only unwrap IO information? VarsState is a custom datatype I have made to use with the State monad/ </p>
  
  <p>However, if that is the problem and I assume it is, I don't know how to transmit this simple string to maybe_compile_prog. Really, that's all I want to do - give a string to maybe_compile_prog.</p>
  
  <p>Perhaps there's some neat way to unwrap this state monad? Perhaps it's possible to rewrite "compile" so that it takes in some state monad information whilst it runs, but then just returns a string (not wrapped in any monad)? </p>
  
  <p>Please let me know if I'm missing any information. </p>