module LUB where class (Retraction a c, Retraction b c) => LUB a b c | a b -> c where leftEmbed :: b -> a -> c leftEmbed _ a = embed a rightEmbed :: a -> b -> c rightEmbed _ b = embed b instance LUB Int Int Int instance (IntEmbed b, IntEmbed a, Retraction a a, Retraction b b) => LUB Int (a->b) (a->b) instance (IntEmbed a, IntEmbed b, Retraction a a, Retraction b b) => LUB (a->b) Int (a->b) instance (LUB a1 b1 c1, LUB a2 b2 c2) => LUB (a1->a2) (b1->b2) (c1->c2) (-->) :: (a->b) -> (c->d) -> (b->c) -> a -> d f --> g = \ h -> g . h . f class Retraction a b where embed:: a->b project:: b->a instance (Retraction a c,Retraction b d) => Retraction (a->b) (c->d) where embed = project --> embed project = embed --> project class IntEmbed a where a_to_int :: a -> Int int_to_a :: Int -> a instance IntEmbed a => Retraction Int a where embed = int_to_a project = a_to_int instance IntEmbed Int where a_to_int = id int_to_a = id instance (IntEmbed a,IntEmbed b) => IntEmbed (a->b) where a_to_int f = a_to_int (f (error "function is not a number")) int_to_a n _ = int_to_a n class (Retraction a b,IntEmbed b,SelfEmbed b) => Full a b | a -> b instance Full Int Int instance (Full a x, Full b y, LUB x y c, Retraction a c, Retraction b c, IntEmbed c, SelfEmbed c) => Full (a->b) (c->c) class SelfEmbed a where apply :: a -> a -> a lambd :: (a->a) -> a instance SelfEmbed Int where apply n _ = n lambd f = f (error "use of function as number") instance SelfEmbed a => SelfEmbed (a->a) where apply = lambd --> apply lambd = apply --> lambd