altcomposition-0.2.2.0: Alternative combinators for unorthodox function composition

Safe HaskellSafe-Inferred
LanguageHaskell2010

Data.AltComposition

Description

Compose functions with higher arity.

Ever tried something like this:

(length . (++)) stringA stringB

Only to find out that you can't? The second function takes two parameters, and as such the simple function composition does not work.

A well known solution to this problem is this fun operator:

(.).(.) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)

And this is quite general:

((.).(.).(.)) :: (d -> e) -> (a -> b -> c -> d) -> (a -> b -> c -> e)

See the following link to gain a intuition for how this works: https://stackoverflow.com/questions/17585649/composing-function-composition-how-does-work

However, in real use these suffer from some problems, namely:

  • They cannot be used infix, even with ticks (at least in ghci).
  • They are quite verbose.

Then, someone thought about using a new symbol instead:

(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)

And for each new parameter, you would add a dot

(.:.) :: (d -> e) -> (a -> b -> c -> d) -> (a -> b -> c -> e)

And so on, to .::, .::., etc. This is the approach taken by the "composition" package, which inspired this one. It can be found at:

http://hackage.haskell.org/package/composition

This package is included in (and re-exported from) this AltComposition.

So, why define a new package?

It does not scale well for other combinations. Let say I want (+) . (*), a function that takes three parameters, uses the first two in the multiplication, and then adds the third parameter with the result. And what if I want to feed to the first binary function as the second parameter of the second function?

The scheme proposed here is a little more verbose than the one from the "composition" package, but it allows for a precise indication of where the result of the first function is applied on the second function using the % symbol (remember printf %). So, the following operator:

*%*.**

Takes a binary function, and composes it with a ternary function, aplying its result as the middle parameter.

Its all a matter of opinion, and I strongly recomend that you use standard haskell syntax instead of these, for more portable code.

Also, many of these verbose operators have simpler counterparts. This is either noted as Deprecation, or a single note.

However, I still find myself writing the *%.*** operators myself, and I trust the deprecations to warn me about the simpler alternatives.

If you need even higher arity, first check your code, then refactor your code, and if you still need it, please send a pull request!

Synopsis

Documentation

(%.**) :: (c -> d) -> (a -> b -> c) -> a -> b -> d infixr 9 Source

Compose a binary function with a unitary function

Note: you should use idiomatic haskell instead

(.).(.) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(f %.** g) x y = f (g x y)
(f .: g) x y = f (g x y)

(%.***) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e infixr 9 Source

Compose a ternary function with a unitary function

Note: you should use idiomatic haskell instead

(.).(.).(.) :: (d -> e) -> (a -> b -> c -> d) -> (a -> b -> c -> e)
(f %.*** g) x y z = f (g x y z)
(f .:. g) x y z = f (g x y z)

(%.****) :: (e -> f) -> (a -> b -> c -> d -> e) -> a -> b -> c -> d -> f infixr 9 Source

Compose a quaternary function with a unitary function

Note: you should use idiomatic haskell instead

(.).(.).(.).(.) :: (e -> f) -> (a -> b -> c -> d -> e) -> (a -> b -> c -> d -> f)
(f %.**** g) w x y z = f (g w x y z)
(f .:: g) w x y z = f (g w x y z)

(%*.*) :: (b -> c -> d) -> (a -> b) -> a -> c -> d infixr 9 Source

Deprecated: This is the same as just (.)

Compose a unary function with a binary function, applying the result of the unary function as the first parameter of the binary function.

Note: DO NOT USE. Equivalent to ..

(f %*.* g) x y = f (g x) y <=> f . g

(%*.**) :: (c -> d -> e) -> (a -> b -> c) -> a -> b -> d -> e infixr 9 Source

Deprecated: Use f %.** g or .: instead

Compose a binary function with another binary function, applying the result of the first binary function as the first parameter of the second binary function.

Note: DO NOT USE. Equivalent to flip f . g.

(f %*.** g) x y z = f (g x y) z

(%*.***) :: (d -> e -> f) -> (a -> b -> c -> d) -> a -> b -> c -> e -> f infix 9 Source

Deprecated: Use f %.*** g or f .:. instead

Compose a ternary function with a binary function, applying the result of the ternary function as the first parameter of the binary function.

(f %*.*** g) x y w z = f (g x y w) z

(*%.*) :: (b -> c -> d) -> (a -> c) -> a -> b -> d infixr 9 Source

Compose a unary function with a binary function, applying the result of the unary function as the second parameter of the binary function.

Note: DO NOT USE. Equivalent to flip f . g.

(f *%.* g) x y = f y (g x)

(*%.**) :: (c -> d -> e) -> (a -> b -> d) -> a -> b -> c -> e infixr 9 Source

Compose a binary function with another binary function, applying the result of the first binary function as the second parameter of the second binary function.

Note: DO NOT USE. Equivalent to flip f .: g or flip f %.** g.

(f *%.** g) x y z = f z (g x y)

(*%.***) :: (d -> e -> f) -> (a -> b -> c -> e) -> a -> b -> c -> d -> f infix 9 Source

Compose a ternary function with a binary function, applying the result of the ternary function as the second parameter of the binary function.

Note: DO NOT USE. Equivalent to flip f .:. g or flip f %.*** g.

(f *%.*** g) x y w z = f z (g x y w)

(%**.*) :: (b -> c -> d -> e) -> (a -> b) -> a -> c -> d -> e infix 9 Source

Deprecated: This is the same as just (.)

Compose a unary function with a ternary function, applying the result of the unary function as the first parameter of the ternary function.

Note: DO NOT USE. Equivalent to ..

(f %**.* g) x y z = f (g x) y z

(%**.**) :: (c -> d -> e -> f) -> (a -> b -> c) -> a -> b -> d -> e -> f infix 9 Source

Deprecated: Use f %.** g or f .: instead

Compose a binary function with a ternary function, applying the result of the binary function as the first parameter of the ternary function.

(f %**.** g) x y w z = f (g x y) w z

(%**.***) :: (f -> d -> e -> g) -> (a -> b -> c -> f) -> a -> b -> c -> d -> e -> g infix 9 Source

Deprecated: Use f %.*** g or f .:. instead

Compose a ternary function with another ternary function, applying the result of the first ternary function as the first parameter of the last ternary function.

(f %**.*** g) v w x y z = f (g v w x) y z

(*%*.*) :: (b -> c -> d -> e) -> (a -> c) -> a -> b -> d -> e infix 9 Source

Compose a unary function with a ternary function, applying the result of the unary function as the second parameter of the ternary function.

(f *%*.* g) x y z = f y (g x) z

(*%*.**) :: (c -> d -> e -> f) -> (a -> b -> d) -> a -> b -> c -> e -> f infix 9 Source

Deprecated: Use f *%.** g instead

Compose a binary function with a ternary function, applying the result of the binary function as the second parameter of the ternary function.

Note: DO NOT USE. Equivalent to flip f .: g or flip f %.** g.

(f *%*.** g) x y w z = f w (g x y) z

(*%*.***) :: (d -> f -> e -> g) -> (a -> b -> c -> f) -> a -> b -> c -> d -> e -> g infix 9 Source

Deprecated: Use f *%.*** g instead

Compose a ternary function with another ternary function, applying the result of the first ternary function as the second parameter of the last ternary function.

Note: DO NOT USE. Equivalent to flip f .:. g or flip f %.*** g.

(f *%*.*** g) v w x y z = f y (g v w x) z

(**%.*) :: (b -> c -> d -> e) -> (a -> d) -> a -> b -> c -> e infix 9 Source

Compose a unary function with a ternary function, applying the result of the unary function as the third parameter of the ternary function.

(f **%.* g) x y z = f y z (g x)

(**%.**) :: (c -> d -> e -> f) -> (a -> b -> e) -> a -> b -> c -> d -> f infix 9 Source

Compose a binary function with a ternary function, applying the result of the binary function as the third parameter of the ternary function.

(f **%.** g) x y w z = f w z (g x y)

(**%.***) :: (d -> e -> f -> g) -> (a -> b -> c -> f) -> a -> b -> c -> d -> e -> g infix 9 Source

Compose a ternary function with another ternary function, applying the result of the first ternary function as the third parameter of the last ternary function.

(f **%.*** g) v w x y z = f y z (g v w x)

(%***.*) :: (f -> b -> c -> d -> g) -> (a -> f) -> a -> b -> c -> d -> g infix 9 Source

Deprecated: This is the same as just (.)

Compose a unary function with a quaternary function, applying the result of the first unary function as the first parameter of the quaternary function.

(f %***.* g) w x y z = f (g w) x y z

(%***.**) :: (f -> c -> d -> e -> g) -> (a -> b -> f) -> a -> b -> c -> d -> e -> g infix 9 Source

Deprecated: This is the same as just %.** or .:

Compose a binary function with a quaternary function, applying the result of the first binary function as the first parameter of the quaternary function.

(f %***.** g) v w x y z = f (g v w) x y z

(?.) :: Category cat => Bool -> cat a a -> cat a a Source

Conditional composition. Borrowed (and modified) from http://hackage.haskell.org/package/cond-0.4.0.2 If the predicate is False, id is returned instead of the second argument. This function, for example, can be used to conditionally add functions to a composition chain.

(.$) :: (b -> c) -> (a -> b) -> a -> c infixl 8 Source

Slightly Lower fixity function composition for use with ?..

(§) :: (a -> b) -> a -> b infixr 8 Source

Just like ($), but with higher precedence than (<>), but still lower than (.). Similar to Diagrams.Util '#', but without flipped arguments.

(&&\) :: (a -> Bool) -> (a -> Bool) -> a -> Bool infixr 3 Source

Group conditions with &&. Useful for filter.

Note: an easy mnemonic to remember is that operators ending in \ (lambda) imply that their parameters are functions instead of values (in this particular case, boolean tests)

(f &&\ g) x = f x && g x

(||\) :: (a -> Bool) -> (a -> Bool) -> a -> Bool infixr 2 Source

Group conditions with || Useful for filter.

Note: an easy mnemonic to remember is that operators ending in \ (lambda) imply that their parameters are functions instead of values (in this particular case, boolean tests)

(f ||\ g) x = f x || g x

for :: Functor f => f a -> (a -> b) -> f b Source

fmap with its arguments reversed.

http://www.reddit.com/r/haskell/comments/qy990/suggestion_for_flip_map/

for  = flip fmap
with = flip fmap

with :: Functor f => f a -> (a -> b) -> f b Source

fmap with its arguments reversed.

http://www.reddit.com/r/haskell/comments/qy990/suggestion_for_flip_map/

for  = flip fmap
with = flip fmap