[Yhc] Yhc using mtl

Twan van Laarhoven twanvl at gmail.com
Sat Apr 7 13:42:20 EDT 2007


Hallo Yhc developers,

While I was in a masochistic mood this week, I decided to change Yhc to
use proper monads. The old State.hs 'monad' was based around the
functions (>>>=) and (>>>), representing a WriterT State monad. They had
some quirky features, like different output state types, and because of
the writer monad, there were lots of functions taking dummy environment
parameters. There was also a different State0 s type representing State
s ().

I have replaced this mess by usage of the mtl, in particular
Control.Monad.State and Control.Monad.Writer. Usage of (>>>=) is
replaced by do notation. As replacement for the (=>>>) operator I use
(<*>) and (<$>) based on Control.Applicative.

I also added a new class "MonadIS" for monads that carry IntState around.
  > class Monad m => MonadIS m where
  >     getIS :: m IntState
  >     putIS :: IntState -> m ()
Most functions are generalized over this class. And to further improve
the readability, all state and environment types are now records.


Now, I may have introduced some bugs. The code was rather fond of
reusing variable names like
  > case liftExp exp state of
  >   (exp, state) -> ...
While I tried to be careful, it is possible that somewhere there is a
reference to an old value.
Yhc does still pass the test suite.

I may have also removed some of the strictness, in the old code =>>>
(aka. <*>) was strict in the state, after the cleanup it no longer is.
This could be fixed by using a different monad. There is already a
StrictState monad in State.hs which I used for debugging (to get traces
in some sensible order).

I also changed "case x of (a,b) -> y" into "let (a,b) = x" in do blocks.
Usually either a or b is examined afterwards anyway, so it should not
matter much for the strictness.

Unfortunately, the code now requires -fglasgow-exts (or a LANGUAGE
pragma) in some places. The only reason for this is FlexibleInstances
for the instance:
  > instance MonadIS (State IntState) where ...
If this is a problem it might be possible to work around it by changing
it to:
  > class HasIntState a
  > instance HasIntState a => MonadIS (State a)
But IMO FlexibleInstances are a noncontroversial extension, and they are
supported by most compilers.

Finally, it should be noted that I kind of gave up at the end; the type
checker just uses runState to get around the monads. The reason for this
is that I saw a circular reference there somewhere, and I decided it was
best not to mess with it.


The patch is too big to send by email to this list, so it can be 
downloaded from
  http://twan.home.fmf.nl/yhc-mtl.patch.gz

Twan van Laarhoven


More information about the Yhc mailing list