-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Wrap together data and it's constraints. -- -- This package, together with its dependency polydata-core, -- allows one to pass data, particularly functions, together with a -- constraint which describes how polymorphic that data is. This -- constraint can then be used in a generic way to produce quite -- polymorphic functions, for example, a "map" function that works on a -- pair of two different types. -- -- See Data.Poly for a basic tutorial. @package polydata @version 0.2 module Data.Poly.Functor -- | A very generic class for a map function on heterogeneous data -- structures (i.e. those with differing types). -- -- This allows you to do things like: -- --
-- >>> hmap triple (3 :: Int, 4.5 :: Float) -- (9 :: Int, 13.5 :: Float) ---- -- hmap takes as it's function a Poly, as of course you'd -- want a polymorphic function. -- -- The return type defined in the class is very vague, indeed it's just -- t to be detailed in the instances, because unlike a normal -- map function, how hmap changes the type depends a lot on -- the type it's applied to, there's no simple f a -> f b. -- -- Currently only instances are defined are for 2 and 3 tuples, nag me if -- you want larger ones. -- -- It's worth noting how the instances are defined, for example, for the -- 2 tuples, there are 3 instances defined. This is primarily to help -- type inference. We don't know too much about the types hmap -- will produce, but we do know, if we feed hmap a pair, we should -- get a pair back. Likewise, if the result of hmap is a pair, -- then the input should be a pair. -- -- So we provide both instances where the input is a pair, and when the -- output is a pair. In both of these instances, we then in the -- constraints section (which happens after instance selection) ensure -- the other argument is also a pair. -- -- The "know both are pairs already" case just needs to be added as a -- specific overlapping instance so the compiler has a most specific -- match when it already knows both input and output are pairs. class PolyFunctor t hmap :: forall c. (PolyFunctor t, PolyFunctorConstraint c t) => Poly c -> t instance Control.IndexT.Tuple.IsTuple 2 a => Data.Poly.Functor.PolyFunctor (a -> (b0, b1)) instance Control.IndexT.Tuple.IsTuple 2 b => Data.Poly.Functor.PolyFunctor ((a0, a1) -> b) instance Data.Poly.Functor.PolyFunctor ((a0, a1) -> (b0, b1)) instance Control.IndexT.Tuple.IsTuple 3 a => Data.Poly.Functor.PolyFunctor (a -> (b0, b1, b2)) instance Control.IndexT.Tuple.IsTuple 3 b => Data.Poly.Functor.PolyFunctor ((a0, a1, a2) -> b) instance Data.Poly.Functor.PolyFunctor ((a0, a1, a2) -> (b0, b1, b2)) module Data.Poly.Function -- | 'mkPolyHomoFunc1 simply represents a function from t -> t, -- possibly constrained. -- -- For example, this is how to write a polymorphic version of "triple": -- --
-- mkPolyHomoFunc1 @Num (*3) --mkPolyHomoFunc1 :: forall c. (forall t. c t => t -> t) -> Poly ((IsHomoFunc 1) &&& ((Arg 0) `IxConstrainBy` c)) -- | 'mkPolyFunc1 is for one argument functions with differing arguments. -- -- For example, this is how to write a polymorphic version of -- toInteger: -- --
-- mkPolyFunc1 @Integral @(Equal Integer) toInteger ---- -- Note that something like Just :: t -> Maybe t this -- convience function is not helpful for, because the two constraints you -- pass here are separate. mkPolyFunc1 :: forall c1 c2. (forall t1 t2. (c1 t1, c2 t2) => t1 -> t2) -> Poly (((IsFunc 1) &&& ((Arg 0) `IxConstrainBy` c1)) &&& ((Result 1) `IxConstrainBy` c2)) -- | 'mkPolyHomoFunc2 simply represents a function from t -> t -> -- t, possibly constrained. -- -- For example, this is how to write a polymorphic version of "add": -- --
-- mkPolyHomoFunc2 @Num (+) --mkPolyHomoFunc2 :: forall c. (forall t. c t => t -> t -> t) -> Poly ((IsHomoFunc 2) &&& ((Arg 0) `IxConstrainBy` c)) -- | 'mkPolyArgFunc2 represents a function from t -> t -> r, -- with two constraints, one for the arguments, one for the result. -- -- For example, this is how to write a polymorphic version of "eq": -- --
-- mkPolyHomoArgFunc2 @Eq @(Equal Bool) (==) --mkPolyHomoArgFunc2 :: forall c1 c2. (forall t1 t2. (c1 t1, c2 t2) => t1 -> t1 -> t2) -> Poly (((IsHomoArgFunc 2) &&& ((Arg 0) `IxConstrainBy` c1)) &&& ((Result 2) `IxConstrainBy` c2)) -- | Handy type class for expressing an "is equal to" constraint, because -- as a class it can be partially applied. -- -- For example, whilst Num is a constraint function from (* -- -> Constraint) such that (Num t) succeeds only if -- t is a Num, Equal Int is a constraint -- function such that (Equal Int) t succeeds only if t -- is an Int. -- -- For example: -- --
-- mkPolyFunc1 @Integral @(Equal Integer) toInteger ---- -- Is a polymorphic toInteger function. class (a ~ b) => Equal a b -- | The empty constraint: -- --
-- Empty a ---- -- always succeeds. class Empty a instance (Control.IndexT.Function.IsFunc 1 f, c1 (Control.IndexT.IndexT 0 f), c2 (Control.IndexT.Function.ResultT 1 f)) => Data.Poly.Function.PolyFunc1Constraints c1 c2 f instance (Control.IndexT.Function.IsHomoFunc 1 f, c (Control.IndexT.IndexT 0 f)) => Data.Poly.Function.PolyHomoFunc1Constraints c f instance a ~ b => Data.Poly.Function.Equal a b instance Data.Poly.Function.Empty a