haskell - Understanding type constraints -
my particular problem may have existential types i'm not sure won't put in title.
anyways, here's i'm trying do.
have entity
type wraps on heterogeneous list of components. then, have hascomponent b
typeclass denotes list b
has component of type a
. here's how i've written it, , classes instances.
data entity c = entity c data compnode c n = compnode c n data compend = compend class hascomponent b getcomponent :: b -> instance hascomponent (compnode n) getcomponent (compnode _) = instance hascomponent n => hascomponent (compnode b n) getcomponent (compnode _ n) = getcomponent n instance hascomponent b => hascomponent (entity b) getcomponent (entity b) = getcomponent b
there's hascomponent
instance entity
. that's convenience.
so far, compiles.
now, i'd try out. i've made displaydata a
type holds data of type a
that's meant displayed. 1 of components. i've made displayer a
wrapper around function of type a -> io ()
. component meant provide way show data.
data displaydata = displaydata data displayer = displayer (a -> io ())
now these 2 components should play nicely together. wanted write function display
takes entity
satisfies constraints , displays it.
this attempt
display :: (hascomponent (displaydata a) c, hascomponent (displayer a) c) => entity c -> io () display e = f displayer f = getcomponent e :: displayer displaydata = getcomponent e :: displaydata
what mean is: "if there exists type such (hascomponent (displaydata a) c, hascomponent (displayer a) c)
true, display
can take entity c
, produce io action."
what think might mean instead is: "if (hascomponent (displaydata a) c, hascomponent (displayer a) c)
true , every type a, display
can take entity c
, produce io action.
the error this
could not deduce (hascomponent (displaydata a0) c) arising ambiguity check `display' context (hascomponent (displaydata a) c, hascomponent (displayer a) c) bound type signature display :: (hascomponent (displaydata a) c, hascomponent (displayer a) c) => entity c -> io () @ components.hs:24:12-94 type variable `a0' ambiguous in ambiguity check for: forall c a. (hascomponent (displaydata a) c, hascomponent (displayer a) c) => entity c -> io () defer ambiguity check use sites, enable allowambiguoustypes in type signature `display': display :: (hascomponent (displaydata a) c, hascomponent (displayer a) c) => entity c -> io ()
how do want here?
first of all, reference type variables in type signature body of function, need enable scopedtypevariables, , add forall type:
{-# language scopedtypevariables #-} display :: forall c . (hascomponent (displaydata a) c, hascomponent (displayer a) c) => entity c -> io () display e = f displayer f = getcomponent e :: displayer displaydata = getcomponent e :: displaydata
but still produce error. issue type a
mentioned in context, not actual type. there no way compiler ever instantiate type. have several options.
you can add "dummy" parameter contains type:
display :: forall c proxy . (hascomponent (displaydata a) c, hascomponent (displayer a) c) => proxy -> entity c -> io () display _ e = f ...
or, can add functional dependency class, , pragmas:
{-# language overlappinginstances, undecidableinstances #-} class hascomponent b | b ->
which says type a
determined type b
. in case, first form compile.
Comments
Post a Comment