haskell - Lowering functions to an embedded language -


how can lower haskell function embedded language in typesafe manner possible. in particular, let's assume have value type like

data type t   num  :: type int   bool :: type bool  data ty = tnum | tbool deriving eq  data tagged t = tagged (type t) t deriving typeable data dynamic  = forall t . typeable t => dynamic (tagged t) deriving typeable  forget :: typeable t => tagged t -> dynamic forget = dynamic  remember :: typeable b => dynamic -> maybe b remember (dynamic c) = cast c 

and want convert function (issucc :: int -> int -> bool) product of dynamic form , type information, this

data splitfun = sf { dynamic    :: [dynamic] -> dynamic                     , inputtypes :: [ty]                     , outputtype :: ty                    } 

such apply function

(\(a:b:_) -> issucc b) == apply (makedynamicfn issucc) 

modulo possible exceptions thrown if dynamic types don't match. or, more explicitly, i'd find makedynamicfn :: funtype -> splitfun. isn't proper haskell type , there's unlikely way pull types issucc itself, might more like

anint . anint . retbool $ issucc :: splitfun 

where anint , retbool have printf-style types.

is such thing possible? there way simulate it?

to implement function of type funtype -> splitfun, we'll use standard type class machinery deconstruct function types.

now, implementing function directly turns out hard. inputtypes , outputtype recursive case, have apply function; can apply function inside dynamic field, gives no way fill other fields. instead, we'll split task two: 1 function give ty information, other construct [dynamic] -> dynamic function.

data proxy = proxy  class split r     dynfun :: r -> [dynamic] -> dynamic     tyinfo :: proxy r -> ([ty], ty)      split :: r -> splitfun     split f = let (i, o) = tyinfo (proxy :: proxy r)               in  sf (dynfun f) o 

now, tyinfo doesn't need function, use proxy pass type information without needing use undefined on place. note need scopedtypevariables able refer type variable r instance declaration. clever use of astypeof might work.

we have 2 base cases: bool , int:

instance split int     dynfun _ = forget (tagged num i)     tyinfo _ = ([], tnum)  instance split bool     dynfun b _ = forget (tagged bool b)     tyinfo _ = ([], tbool) 

there no input types , since have value, not need ask more dynamic values , return dynamic of particular value.

next, have 2 recursive cases: bool -> r , int -> r

instance (split r) => split (int -> r)     dynfun f (d:ds) = case remember d :: maybe (tagged int) of         (tagged _ i) -> dynfun (f i) ds         nothing           -> error "dynfun: wrong dynamic type"     dynfun f []     = error "dynfun: not enough arguments"      tyinfo _ = case tyinfo (proxy :: proxy r) of          (i, o) -> (tnum:i, o)  instance (split r) => split (bool -> r)     dynfun f (d:ds) = case remember d :: maybe (tagged bool) of         (tagged _ b) -> dynfun (f b) ds         nothing           -> error "dynfun: wrong dynamic type"     dynfun f []     = error "dynfun: not enough arguments"      tyinfo _ = case tyinfo (proxy :: proxy r) of          (i, o) -> (tbool:i, o) 

these 2 need flexibleinstances. dynfun examines first dynamic argument , if it's okay, can safely apply function f , continue there. make dynfun :: r -> [dynamic] -> maybe dynamic, that's trivial change.


now, there's duplication going on. introduce class, such as:

class concrete r     getty   :: proxy r -> ty     gettype :: proxy r -> type r 

and write:

instance (typeable r, concrete r) => split r     dynfun r _ = forget (tagged (gettype (proxy :: proxy r)) r)     tyinfo _ = ([], getty (proxy :: proxy r))  instance (typeable r, concrete r, split s) => split (r -> s)     dynfun f (d:ds) = case remember d :: maybe (tagged r) of         (tagged _ v) -> dynfun (f v) ds         -- ...      tyinfo _ = case tyinfo (proxy :: proxy s) of         (i, o) -> (getty (proxy :: proxy r):i, o) 

but needs both overlappinginstances , undecidableinstances.


Comments

Popular posts from this blog

css - Which browser returns the correct result for getBoundingClientRect of an SVG element? -

gcc - Calling fftR4() in c from assembly -

.htaccess - Matching full URL in RewriteCond -