[Haskell-cafe] Compiler's bane
Jonathan Cast
jonathanccast at fastmail.fm
Thu Sep 4 13:50:24 EDT 2008
On Thu, 2008-09-04 at 18:41 +0100, Andrew Coppin wrote:
> Ryan Ingram wrote:
> > It's pretty simple, I think.
> >
> > type ExpGen = ReaderT [String] Gen
> >
> > arbExp :: ExpGen Expression
> > -- exercise for the reader
> >
> > instance Arbitrary Expression where
> > arbitrary = runReaderT arbExp []
> > coarbitrary = coarbExp
> >
> > coarbExp (Var s) = variant 0 . coarbitrary s
> > coarbExp (Apply a b) = variant 1 . coarbitrary a . coarbitrary b
> > coarbExp (Lambda s e) = variant 2 . coarbitrary s . coarbitrary e
> >
> > instance Arbitrary Char where
> > arbitrary = elements "abcdefghijklmnopqrstuvwxyz_"
> > coarbitrary = coarbitrary . fromEnum
> >
>
> o_O
>
> I love the way other people have wildly different ideas of "simple" than
> me. I'm staring at this and completely failing to comprehend it. (But
> then, anything with "co" in the name generally makes little sense to
> me...) Why on earth would you need a reader monad? Surely if you want to
> add bound variables and then later query what variables are bound, you'd
> want a state monad? Hmm, I'm completely lost here.
Motto (off-the-cuff): State monads are for APIs with function names like
`set'; reader monads are for APIs with function names like `with'. In
this case, you definitely do not want to bring names into scope with
bringNameIntoScope :: Name -> ExpGen ()
because then you'd just have to implement
bringNameOutofScope :: Name -> ExpGen ()
and remember to call it after you've generated the body of the lambda,
except that you have to check before bringing the name into scope
whether it's already in scope and if so make sure it's still in scope
afterwards.
A simpler alternative is to pull out the entire scope, using get, save
it off, modify the state, and then put it back later:
withNameInScope :: Name -> ExpGen alpha -> ExpGen alpha
withNameInScope name a = do
scope <- get
modify (name:)
x <- a
set scope
return x
But by adopting that API, you're suggesting the use of a reader monad to
implement scoping, since withNameInScope would then be just
withNameInScope name = local (name:)
jcc
http://haskell.org/ghc/docs/latest/html/libraries/mtl/Control-Monad-Reader-Class.html#v%3Alocal
More information about the Haskell-Cafe
mailing list