{-# OPTIONS_GHC -Wall -fwarn-tabs #-} ---------------------------------------------------------------- -- 2012.01.29 -- | -- Module : Data.Function.Pointless -- Copyright : Copyright (c) 2009--2012 wren ng thornton -- License : BSD -- Maintainer : wren@community.haskell.org -- Stability : provisional -- Portability : Haskell98 -- -- Pointless fun :) ---------------------------------------------------------------- module Data.Function.Pointless ( -- * Multicomposition -- | Based on . -- These combinators allow you to easily modify the types of a -- many-argument function with syntax that looks like giving -- type signatures. For example, -- -- > foo :: A -> B -> C -- > -- > albert :: X -> A -- > beth :: Y -> B -- > carol :: C -> Z -- > -- > bar :: X -> Y -> Z -- > bar = foo $:: albert ~> beth ~> carol ($::), (~>), (!~>) -- * Composition for arity 2 , (.:), (.^) -- * Strict composition , (.!) ) where ---------------------------------------------------------------- ---------------------------------------------------------------- {- TODO: actually put this in. -- Note: @pl had nothing to do with the invention of this combinator. I constructed it by hand after noticing a common pattern. -- Cale swing :: (((a -> b) -> b) -> c -> d) -> c -> a -> d swing = flip . (. flip id) swing f = flip (f . runCont . return) swing f c a = f ($ a) c -- Some examples of use: swing map :: forall a b. [a -> b] -> a -> [b] swing any :: forall a. [a -> Bool] -> a -> Bool swing foldr :: forall a b. b -> a -> [a -> b -> b] -> b swing zipWith :: forall a b c. [a -> b -> c] -> a -> [b] -> [c] swing find :: forall a. [a -> Bool] -> a -> Maybe (a -> Bool) -- applies each of the predicates to the given value, returning the first predicate which succeeds, if any swing partition :: forall a. [a -> Bool] -> a -> ([a -> Bool], [a -> Bool]) -} ---------------------------------------------------------------- -- | Lift a function for multicomposition. This is like the @::@ -- of a type signature. ($::) :: (a -> b) -> ((a -> b) -> (c -> d)) -> (c -> d) ($::) = flip ($) {-# INLINE ($::) #-} infixl 1 $:: -- | Multicompose a function on the appropriate argument. This is -- like the @->@ arrows in a type signature. (~>) :: (a -> b) -> (c -> d) -> ((b -> c) -> (a -> d)) f ~> g = (. f) . (g .) {-# INLINE (~>) #-} infixr 2 ~> -- | Multicompose a function on the appropriate argument, calling -- the left function eagerly. That is, the resulting function will -- be strict in @a@ if the left argument is strict in @a@ (assuming -- the final function of the multicomposition, the one applied to -- the return value, is also strict). (!~>) :: (a -> b) -> (c -> d) -> ((b -> c) -> (a -> d)) f !~> g = (.! f) . (g .) {-# INLINE (!~>) #-} infixr 2 !~> ---------------------------------------------------------------- -- | Binary composition: pass two args to the right argument before -- composing. -- -- > (f .: g) x y = f (g x y) -- -- or, -- -- > f .: g = curry (f . uncurry g) -- -- This is the same as the common idiom @(f .) . g@ but more easily -- extended to multiple uses, due to the fixity declaration. (.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d) (.:) = (.) . (.) {-# INLINE (.:) #-} infixl 8 .: -- | Secondary composition: compose the right argument on the second -- arg of the left argument. -- -- > (f .^ g) x y = f x (g y) (.^) :: (a -> c -> d) -> (b -> c) -> (a -> b -> d) (.^) = flip .: (.) . flip {-# INLINE (.^) #-} infix 9 .^ -- | Function composition which calls the right-hand function -- eagerly; i.e., making the left-hand function strict in its first -- argument. -- -- > (f .! g) x = f $! g x -- -- This defines the composition for the sub-category of strict -- Haskell functions. If the 'Functor' class were parameterized by -- the domain and codomain categories (e.g., a regular @Functor f@ -- would be @CFunctor (->) (->) f@ instead) then this would allow -- us to define functors @CFunctor (->) (!->) f@ where -- @fmap f . fmap g = fmap (f .! g)@. (.!) :: (b -> c) -> (a -> b) -> a -> c (.!) = (.) . ($!) {-# INLINE (.!) #-} infixr 9 .! -- For some reason this definition is significantly faster than the -- pointful version in the documentation. Even after INLINE. Who knew? -- -- cf vs @($!) .: (.)@ == @\f g x -> f . g $! x@ which stictifies -- the first argument of RH-function. However, this doesn't behave -- the way you may think it should; i.e., it isn't compositional -- in the way you think it should be. ---------------------------------------------------------------- ----------------------------------------------------------- fin.