-- | Module with basic infrastructure for function inheritance -- based on open rercusion. -- -- See the work of William Cook. -- -- We use the following terminology. -- -- * A /closed/ function is an ordinary function. -- -- * A /mixin/ function is an open function that can be -- inherited from, or that extends another open function. -- -- We obtain a closed function from a base mixin 'base' -- and a number of mixin extensions 'e1',...,'en' as follows: -- -- > mixin (en <@> ... <@> e1 <@> base) -- module Control.Mixin.Mixin ( Mixin, (<@>), mixin, mixinId, mixinLift ) where infixl 5 <@> -- | Type of mixin functions. type Mixin a = a -- the 'super' function -> a -- the 'this' function -> a -- the current function -- | Mixin composition. (<@>) :: Mixin a -> Mixin a -> Mixin a (f1 <@> f2) super this = f1 (f2 super this) this -- | Turn a mixin into a closed function. mixin :: Mixin a -> a mixin openF = let closedF = openF errorF closedF errorF = error $ "super called in base mixin" in closedF -- | Mixin identity function. -- -- Identity for mixin composition: -- -- -- > mixinId <@> f == f -- > f <@> mixinId == f -- mixinId :: Mixin a mixinId super this = super -- | Mixin lift function -- -- > mixin . mixinLift = id mixinLift :: (a -> b) -> Mixin (a -> b) mixinLift f _ _ = f