{-| Map the arguments and return value of functions. General use: - @f $* g1 $$ g2 … $$ gn *$ h = \\x1 … xn -> h (f (g1 x1) (g2 x2) … (gn xn))@ Examples: - @on f g = f $* g $$ g *$ id@ - @comparing f = compare $* f $$ f *$ id@ - @f . g = f $* g *$ id@ Related work: - (Conal Elliott, 2008\/11\/24). Introduces composable editors for function arguments and return values. - (Matt Hellige, 2008\/12\/03). Derives a similar operator named @~>@. This operator composes an editor which can then be applied to the subject to edit. This better agrees with Conal's concept of Semantic Editor Combinators. In contrast, @$*@ includes the subject as part of the editor, though you can write @($* g1 $$ g2 … $$ gn *$ h)@ for an editor independent of the subject. Also, @~>@ is right-associative whereas @$*@ and @$$@ are left-associative. - (Conal Elliott, 2016\/01\/15). Package including an implementation of @~>@. -} module Data.Function.Meld ( ($*) , ($$) , (*$) ) where import Prelude (flip) import Control.Category (Category, (.), id) -- | Map a function argument. arg :: Category cat => cat a' a -> cat a b -> cat a' b arg = flip (.) -- | Map a function return value. ret :: Category cat => cat b c -> cat a b -> cat a c ret = (.) -- | Begin melding. -- -- @f $* g1 $$ g2 … $$ gn *$ h = \\x1 … xn -> h (f (g1 x1) (g2 x2) … (gn xn))@ ($*) :: Category cat => cat b c -> cat a b -> cat c d -> cat a d ($*) x f g = ret g (arg f x) infixl 8 $* -- | Continue melding. -- -- @f $* g1 $$ g2 … $$ gn *$ h = \\x1 … xn -> h (f (g1 x1) (g2 x2) … (gn xn))@ ($$) :: Category cat => ((cat b c -> cat a d) -> e) -> cat a b -> cat c d -> e ($$) f g h = f (ret h . arg g) infixl 7 $$ -- | Finish melding. -- -- @f $* g1 $$ g2 … $$ gn *$ h = \\x1 … xn -> h (f (g1 x1) (g2 x2) … (gn xn))@ (*$) :: Category cat => cat a b -> cat a b (*$) = id infixl 6 *$