[Haskell-cafe] Re: Typed Lambda-Expressions withOUT GADTs

oleg at pobox.com oleg at pobox.com
Sun Jan 2 01:57:51 EST 2005


Ashley Yakeley wrote on the first day of 2005:
> This compiled with today's CVS GHC 6.3. I don't think you can do this
> without GADTs.

It seems we can do without GADT -- roughly with the same syntax
(actually, the syntax of expressions is identical -- types differ and
we have to write `signatures' -- i.e., instance declarations). Tested
with GHC 6.2.1.

I especially liked the example
	test3 = (runExpression s) (runExpression k) (runExpression k)
below. Its inferred type is

	-- :t test3: 
	-- test3 :: forall r. r -> r 

so, SKK must be the identity (if it terminates, that is)

{-# OPTIONS -fglasgow-exts #-}
{-# OPTIONS -fallow-undecidable-instances #-}

module Expression where

-- data Sym env r where
--     FirstSym :: Sym (r,xx) r
--     NextSym :: Sym env r -> Sym (a,env) r

class SymT t env r
data FirstSym = FirstSym deriving Show
data NextSym t = NextSym t deriving Show

instance SymT FirstSym (r,xx) r
instance SymT t env r => SymT (NextSym t) (a,env) r

class SymT t env r => RunSym t env r | t env -> r where
    runSym :: t -> env -> r

-- runSym FirstSym (r,xx) = r;
instance RunSym FirstSym (r,xx) r where
    runSym _ (r,xx) = r

instance RunSym var env r => RunSym (NextSym var) (a,env) r where
    runSym (NextSym var) (a,env) = runSym var env -- the code literally



-- data OpenExpression env r where
--   Lambda :: OpenExpression (a,env) r -> OpenExpression env (a -> r);
--   Symbol :: Sym env r -> OpenExpression env r;
--   Constant :: r -> OpenExpression env r;
--   Application :: OpenExpression env (a -> r) -> OpenExpression env a -> 
--                  OpenExpression env r

-- Frankly speaking, the class OpenExpression below isn't necessary
-- We could have gotten by with just RunOpenExpression
-- However, the class OpenExpression makes it easy to formulate
-- the constraint for well-formed expressions.
-- We can use that constraint elsewhere.

class OpenExpression t env r
data Lambda a t = Lambda t deriving Show
data Symbol t = Symbol t deriving Show
data Constant r = Constant r deriving Show
data Application a t1 t2 = Application t1 t2 deriving Show


instance OpenExpression t (a,env) r => OpenExpression (Lambda a t) env (a->r)
instance SymT t env r => OpenExpression (Symbol t) env r
instance OpenExpression (Constant r) env r
instance (OpenExpression t1 env (a->r),
	  OpenExpression t2 env a)
    => OpenExpression (Application a t1 t2) env r


class OpenExpression t env a => RunOpenExpression t env a | t env -> a
--class RunOpenExpression t env a | t env -> a
    where
    runOpenExpression :: t -> env -> a

instance RunOpenExpression (Constant r) env r where
    runOpenExpression (Constant r) _ = r

instance (RunOpenExpression t1 env (b->a),
	  RunOpenExpression t2 env b)
    => RunOpenExpression (Application b t1 t2) env a where
    runOpenExpression (Application t1 t2) env = 
	(runOpenExpression t1 env)
	(runOpenExpression t2 env)
    
instance RunSym var env r => RunOpenExpression (Symbol var) env r where
    runOpenExpression (Symbol var) env = runSym var env

instance RunOpenExpression t (a,env) r
    => RunOpenExpression (Lambda a t) env (a->r) where
    runOpenExpression (Lambda exp) env = \a -> runOpenExpression exp (a,env)

newtype Expression t r = MkExpression (forall env. 
				       RunOpenExpression t env r => t)

runExpression (MkExpression e) = runOpenExpression e ()


sym0 = Symbol FirstSym

sym1 = Symbol (NextSym FirstSym)

sym2 = Symbol (NextSym (NextSym FirstSym))

    -- k = \x.\y -> x = \.\.1
k = MkExpression (Lambda (Lambda sym1))

-- s :: Expression ((a -> b -> c) -> (a -> b) -> a -> c);
-- -- s = \x.\y.\z -> x z (y z) = \.\.\.2 0 (1 0)
s = MkExpression (Lambda 
		  (Lambda 
		   (Lambda 
		    (Application
		     (Application
		      sym2 sym0) (Application sym1 sym0)))))

test1 = (runExpression k) sym0 sym2
test2 = (runExpression k) sym2 sym0

test3 = (runExpression s) (runExpression k) (runExpression k)
-- Note: That can only be the identity!
-- :t test3: 
-- test3 :: forall r. r -> r 

test3' = test3 "It's the identity!!! Look at the type!!!"


	


More information about the Haskell-Cafe mailing list