Ryan Reich
2017-12-27 07:33:09 UTC
I have found it useful to use Dynamic-like existential types such as (fake
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
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.
data Number = forall a. (Num a, Typeable a) => Number a
which supports precisely the same API as Dynamic, but with a Num constrainton 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) atoCDyn :: (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 apparentlyfromCDyn :: (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
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.