Manager [SubUnit] data SubUnit = EmpUnit Employee | DeptUnit Dept data Employee = Employee Person Salary data Person = Person Name Address data Salary = Salary Number type Manager = Employee type Name = String type Address = String MOTIVATION increase :: (Salary -> Salary) -> Company -> Company
-> a instance mapSalary :: MapSalary Salary where increase f a = f a else instance mapSalary :: MapSalary a where increase _ a = a AD HOC OVERLOADING? Too much boilerplate. Need a general solution.
forall a b. TypeRep a -> TypeRep b -> Boolean -instanceOf :: forall a. a -> TypeRep b -> Boolean instanceOf a t = eqTypeRep (typeRep :: _ a) t REIFY TYPES Predefined a == b => TypeRep a == TypeRep b
Type Char TArray :: Type a -> Type (Array a) TFunc :: Type b -> Type c -> Type (Function b c) TTuple :: Type a -> Type b -> Type (Tuple a b) eqTypeRep :: forall a b. TypeRep a -> TypeRep b -> Boolean eqTypeRep TInt TInt = True … MANUALLY - GADTS
(Char ~ a) | TArray (Type b) (a ~ Array b) | TFunc (Type b) (Type c) (a ~ Function b c) | TTuple (Type b) (Type c) (a ~ (Tuple b c)) eqTypeRep :: forall a b. TypeRep a -> TypeRep b -> Boolean eqTypeRep (TInt w1) (TInt w2) = Just $ symm w1 >>> w2 … MANUALLY - WITHOUT GADTS Not extensible Explained later
a increase f a | a `instanceOf` typeRep = f (coerceToSalary a) | otherwise = a coerceToSalary :: forall a. a -> Salary coerceToSalary = unsafeCoerce SOLUTION
a increase f a = case a `instanceOf` typeRep of Just coercion = f (coercion a) Nothing -> a instanceOf :: forall a. a -> TypeRep b -> Maybe (a -> b) instanceOf ta tb | eqTypeRep ta tb = Just (unsafeCoerce identity) | otherwise = Nothing ENCAPSULATE UNSAFE BEHAVIOUR (TYPE WITNESSES)
a increase f a = case cast a of Just n = f n Nothing -> a cast :: forall a b. Typeable a => Typeable b => a -> Maybe b cast a = case a `instanceOf` (typeRep :: _ b) of Nothing -> Nothing Just f -> f a EQUIVALENTLY Runtime cast
-> Maybe (a ~ b) eqT ta tb | eqTypeRep ta tb = Just (unsafeCoerce (identity :: Leibniz a a)) | otherwise = Nothing cast :: forall a b. Typeable a => Typeable b => a -> Maybe b cast a = eqT (typeRep :: _ a) (typeRep :: _ b) :: Maybe (Identity a -> Identity b) # map \f -> runLeibniz f (Identity a) :: Maybe (Identity b) # map unwrap :: Maybe b CAST USING LEIBNIZ
b. Data b => b -> b) -> a -> a instance Data Employee where gmapT f (E per sal) = E (f per) (f sal) instance Data Bool where gmapT f x = x instance Data a => Data [a] where gmapT f [] = [] gmapT f (x:xs) = f x : f xs WRAPPING IT UP
b -> b) -> a -> a everywhere f x = f (gmapT (everywhere f) x) solution :: (Salary->Salary) -> Company -> Company Solution k = everywhere (increase k) NO BOILERPLATE
data Dynamic t = Dynamic (Exists (Dynamic' t)) dynamic :: forall t a. Typeable a => t a -> Dynamic t dynamic a = Dynamic (mkExists (Dynamic' typeRep a)) unwrapDynamic :: forall t a. TypeRep a -> Dynamic t -> Maybe (t a) unwrapDynamic ta (Dynamic e) = e # runExists \(Dynamic' ti v) -> map (\w -> runLeibniz w v) (eqT ti ta) ANOTHER EXAMPLE - DYNAMIC VALUES
(a :: Type -> Type) where tag1 :: Proxy1 a … instance tagInt :: Tag0 Int where tag0 = proxy0 instance tagArray :: Tag1 Array where tag1 = proxy1 … TAGS User Defined Instances
a) where tag1 = proxy1FromTag2 instance tag0FromTag1 :: (Tag1 t, Typeable a) => Tag0 (t a) where tag0 = proxy0FromTag1 … foreign import proxy1FromTag2 :: forall t a. Tag2 t => Typeable a => Proxy1 (t a) foreign import proxy0FromTag1 :: forall t a. Tag1 t => Typeable a => Proxy0 (t a) … TAG CHAINING A -> B -> [A,B] [A,B] -> C -> [A,B,C]
r rl => TypeRow rl -> TypeRep (Record r) foreign import typeRowNil :: TypeRow RL.Nil foreign import typeRowCons :: SProxy s -> TypeRep t -> TypeRow rs -> TypeRow (RL.Cons s t rs) TYPEABLE FOR ROW TYPES A -> A [] S -> T -> R -> (S,T):R