Sun Jul 24 17:22:02 CEST 2011

Let : summary

class Symantics r => SymanticsLet r where
  letS  :: r a -> (r a -> r b) -> r b
  letS term body = body term

instance SymanticsLet Eval 
instance SymanticsLet Code

expr6 = letS (int 3) (\x -> x * x)

The cool thing is that this "just works" for Eval.  It doesn't need
name generation: embedded language uses the binding structure of

However, the code implementation doesn't do what it's supposed to do,
which is to generate names instead of duplicating terms.  This
requires some extra effort.

The problem however is that this brings me back to an old foe: if the
dictionary is encoded in the representation type, what to do when 2
branches with different context are merged?  Maybe this simply can't
happen?  I'm confused so let's just start building it and see where it

I got to this, which does the right thing for expr7 below but feels
horribly wrong:

data Code a = Code { dict :: [(String,String)], code :: String }
            deriving (Eq, Show)

code' x = Code [] $ show x
code1 op (Code d x)                          = Code d (codeApp [op,x])
code2 op (Code d x) (Code d' y)              = Code d (codeApp [op,x,y])
code3 op (Code d x) (Code d' y) (Code d'' z) = Code d (codeApp [op,x,y,z])

codeLet (Code dict term) body = body (Code dict' var) where
  var = "R" ++ (show $ length dict)
  dict' = (var, term):dict
instance Symantics Code where
  let_ = codeLet

expr7 = let_ (int 3) (\x ->
        let_ (x*x)   (\xx -> (xx * xx)))             

*Final> expr7 :: Code Tint
Code {dict = [("R1","(imul R0 R0)"),("R0","3")], code = "(imul R1 R1)"}

It seems that the dictionary should go somewhere completely different.
But where?  Let's first try to construct something that breaks.

Since contexts are nested, the only case in which they can be
different is if one is contained in the other.  Is that enough?

Hmm... i'm going down the drain here.  There has to be a much simpler

There seems to be really no way around making a linear traversal over
the code to replace all intermediate nodes with name and collect the
original node contents.  However, it seems impossible to do this for
the code1, code2, code3 operations above.  Or is it?

Why can't repr be a Monad?  Maybe there's no reason at all why it
cannot be one.

code2 op (Code x) (Code y)          = Code $ codeApp [op,x,y]

can this be replaced by something like:

code2 op x y  = do
      vx <- x
      vy <- y
      return $ print op vx vy

I.e. for the 2-ops the type could be

M a -> M a -> M a

Wait a minute.  Can't this be implemented in terms of let_ directly?