| From: Sebastian Hunt <[EMAIL PROTECTED]>
| Date: Thu, 9 Dec 1993 16:00:13 GMT 

| In the interests of keeping things (ie, the haskell type system)
| as simple as possible, I would vote (if I had a vote) against this
| proposal. Unless, of course, I was persuaded that the extension was
| Really Useful. So Simon: what were those programs?
| 
| Sebastian


OK, here's my example.  I hope it's right.  I was writing a compiler
pass which looked at a data type something like

        data Expr = Let Bind Expr
                  | ...

        data Bind = MkBind String Expr

Then I had three functions, written in continuation-passing styule, as
follows:

        doBinds :: [Bind] -> [Bind]
        doBinds (b:bs) = doBindAndScope b (\b' -> b' : doBinds bs)

        doExpr :: Expr -> Expr
        doExpr (Let b e) = doBindAndScope b (\b' -> Let b' (doExpr e))

        doBindAndScope :: Bind -> (Bind -> a) -> a
        doBindAndScope (MkBind s e) cont = cont (MkBind s (doExpr e))

The trouble is that the mutual recursion between 

        doBindsAndScope         doExpr

means that doBindsAndScope can't be as polymorphic as its type
signature says it should be.  But if it isn't that polymorphic, the
call in doBinds is illegal.  

I solved it like this (UTTERLY YUK YUK), by encapsulating the polymorphism
in a fixed data type which simply tags the various expected types at
which the function can be called.  Not only is this really quite obscure, 
but it also is inefficient at runtime.

        data WhatIsIt = ItsABinds [Bind] | ItsAnExpr Expr

        doBinds :: [Bind] -> [Bind]
        doBinds (b:bs) = case (doBindAndScope b 
                                (\b' -> ItsABinds (b' : doBinds bs))) of
                           ItsABind bs -> bs

        doExpr :: Expr -> Expr
        doExpr (Let b e) = case (doBindAndScope b 
                                  (\b' -> ItsAnExpr (Let b' (doExpr e))) of
                            ItsAnExpr e -> e

        doBindAndScope :: Bind -> (Bind -> WhatIsIt) -> WhatIsIt
        doBindAndScope (MkBind s e) cont = cont (MkBind s (doExpr e))
        
Simon

Reply via email to