Discussion:
Constrained Dynamic variant
Ryan Reich
2017-12-27 07:33:09 UTC
Permalink
I have found it useful to use Dynamic-like existential types such as (fake
data Number = forall a. (Num a, Typeable a) => Number a
which supports precisely the same API as Dynamic, but with a Num constraint
on everything. However, writing that API for this particular type requires
copy-pasting the definitions of fromDyn and fromDynamic as boilerplate,
which is (ahem) stupid. Now that we have the Constraint kind, it is
data CDynamic (c :: Type -> Constraint) = forall a. (c a) => CDynamic
(TypeRep a) a
toCDyn :: (c a, Typeable a) => a -> CDynamic c
fromCDyn :: (c a, Typeable a) => CDynamic c -> a -> a
fromCDynamic :: (c a, Typeable a) => CDynamic c -> Maybe a
relaxCDyn :: CDynamic c -> Dynamic
dynApplyC :: CDynamic c1 -> CDynamic c2 -> Maybe Dynamic
dynAppC :: CDynamic c1 -> CDynamic c2 -> Dynamic
dynTypeRepC :: CDynamic c -> SomeTypeRep
instance Show (CDynamic c)
instance Exception (CDynamic c)
class NoC a where -- intentionally empty, can be used unsaturated
instance NoC a where -- also empty
type Dynamic = CDynamic NoC
-- Specializations of all the above functions
I think it's clear how to fill in the definitions. I added an apparently
necessary function relaxCDyn that also does the obvious thing; I'm not
really happy with its type signature but offhand I can't say how to
generalize it.

I think this is useful, and if I'm not missing anything (obvious or subtle)
about it, I want to propose that it goes into Data.Dynamic.
David Feuer
2017-12-27 08:16:52 UTC
Permalink
You can make relaxation kind of work using a lens-like trick:

type CDynamic (c :: * -> Constraint) =
forall r. (forall a. (Typeable a, c a) => a -> r) -> r

The trouble is that ambiguous types start to pop up pretty quickly, so
I don't know that this would really be a practical approach.
Post by Ryan Reich
I have found it useful to use Dynamic-like existential types such as (fake
data Number = forall a. (Num a, Typeable a) => Number a
which supports precisely the same API as Dynamic, but with a Num constraint
on everything. However, writing that API for this particular type requires
copy-pasting the definitions of fromDyn and fromDynamic as boilerplate,
which is (ahem) stupid. Now that we have the Constraint kind, it is
data CDynamic (c :: Type -> Constraint) = forall a. (c a) => CDynamic
(TypeRep a) a
toCDyn :: (c a, Typeable a) => a -> CDynamic c
fromCDyn :: (c a, Typeable a) => CDynamic c -> a -> a
fromCDynamic :: (c a, Typeable a) => CDynamic c -> Maybe a
relaxCDyn :: CDynamic c -> Dynamic
dynApplyC :: CDynamic c1 -> CDynamic c2 -> Maybe Dynamic
dynAppC :: CDynamic c1 -> CDynamic c2 -> Dynamic
dynTypeRepC :: CDynamic c -> SomeTypeRep
instance Show (CDynamic c)
instance Exception (CDynamic c)
class NoC a where -- intentionally empty, can be used unsaturated
instance NoC a where -- also empty
type Dynamic = CDynamic NoC
-- Specializations of all the above functions
I think it's clear how to fill in the definitions. I added an apparently
necessary function relaxCDyn that also does the obvious thing; I'm not
really happy with its type signature but offhand I can't say how to
generalize it.
I think this is useful, and if I'm not missing anything (obvious or subtle)
about it, I want to propose that it goes into Data.Dynamic.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Loading...