Tue Oct 25 22:13:54 EDT 2011

(->) (Code Tint) as monad

I see that indeed ((->) t) is a monad, and it matches 2 instances.  I
don't see why this is a problem only now; this same code worked

    Overlapping instances for CompileFun
                                ((->) (Code Tint))
                                (Code Tint
                                 -> Code Tfloat
                                 -> Code Tfloat
                                 -> MCode (Code Tfloat, Code Tfloat))
      arising from a use of `termFun'
    Matching instances:
      instance (CompileVar r, CompileData r s, CompileFun s m f) =>
               CompileFun s m (r -> f)
        -- Defined at Compile.hs:(37,10)-(40,35)
      instance (CompileData r s, Monad m) => CompileFun s m (m r)
        -- Defined at Compile.hs:48:10-59
    In the expression: termFun test3'
    In an equation for `it': it = termFun test3'

So the culprit is this one:

instance (CompileData r s, Monad m) => CompileFun s m (m r) where
  compileFun _ mt = ([], liftM compileData mt)

I tried some shuffling but didn't get anywhere.  I've added
IncoherentInstances and that seems to shut it up.  See [1] for more

A little more tinkering made termFun work:

termFun :: CompileFun Term (SC TML.State Term) f => f -> Term
termFun f = Lambda args body where
  (targs, mresult) = compileFun varnames f 
  -- Lambda arguments are variable terms generated from names in varnames
  args = vars targs
  -- Body is a nested expression that ends in a Ret expression.
  body = runMCode mresult k
  k _ cs = Ret $ vars cs
  -- Both input and output terms are expected to be variable references.
  unRef (Ref v) = v
  vars = map unRef

test a b = do
  s <- add a b
  p <- mul a b
  return (s, p)

test' = test :: Code Tfloat -> Code Tfloat 
                -> MCode (Code Tfloat, Code Tfloat)

t = termFun test'

Lambda [Var f "i0" 0,
        Var f "i1" 0]
  (Let (Var f "t0" 0)
          (Op f "add" [Ref (Var f "i0" 0),
                       Ref (Var f "i1" 0)])
  (Let (Var f "t1" 0)
          (Op f "mul" [Ref (Var f "i0" 0),
                       Ref (Var f "i1" 0)])
  (Ret [Var f "t0" 0,
        Var f "t1" 0])))

This is amazing, isn't it?  f -> Term ;)

Another milestone.
The rest seems a bit more straightforward.

[1] http://www.haskell.org/ghc/docs/6.6/html/users_guide/type-extensions.html