简体   繁体   中英

Haskell function composition

I am reading this tutorial on Haskell. They define function composition as the following:

(.)                     :: (b->c) -> (a->b) -> (a->c)
f . g                   = \ x -> f (g x)

No examples were provided, which I believe would enlighten me as to what is being defined here.

Can someone provide a simple example (with explanation) of how function composition is used?

Function composition is a way to "compose" two functions together into a single function. Here's an example:

Say you have these functions:

even :: Int -> Bool
not :: Bool -> Bool

and you want to define your own myOdd :: Int -> Bool function using the two above.

The obvious way to do this is the following:

myOdd :: Int -> Bool
myOdd x = not (even x)

But this can be done more succinctly using function composition:

myOdd :: Int -> Bool
myOdd = not . even

The myOdd functions behave exactly the same, but the second one is created by "glue-ing" two functions together.

A scenario where this is especially useful is to remove the need for an explicit lambda. Eg:

map (\x -> not (even x)) [1..9]

can be rewritten to:

map (not . even) [1..9]

A bit shorter, less room for errors.

Fun side note. Function composition is the equivalent of a syllogism in logic:

All men are mortal. Socrates is a man. Therefore, Socrates is mortal.

A syllogism composes two material implications into one:

(Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal)

Therefore...

(b -> c) -> (a -> b) -> (a -> c)

... which is the type of the . function.

The composition of f and g is a function that first applies g to its argument, then f to the value returned by g . It then returns the return value of f .

This identity may be enlightening:

f (g x) = (f . g) x

If you have a Java/C background, consider this example:

int f(int x);
int g(int x);
int theComposition(int x) { return f(g(x)); }

This example is contrived, but suppose we have

sqr x = x * x  
inc x = x + 1

and we want to write a function that computes x^2+1. We can write

xSquaredPlusOne = inc . sqr

(which means

xSquaredPlusOne x = (inc . sqr) x

which means

xSquaredPlusOne x = inc(sqr x)

since f=inc and g=sqr).

Function composition is a way to chain two or more functions together. It's often likened to shell piping. For example, in a Unix-style shell, you might write something like

cat foo.txt | sort -n | less

This runs cat , feeds its output to sort , and feeds the output from that to less .

Strictly, this is like the Haskell $ operator. You might write something like

sum $ sort $ filter (> 0) $ my_list

Notice that, unlike the shell example, this reads from right to left. So we start with my_list as input, then we run filter over it, then we sort it, and then we calculate the sum of it.

The function composition operator, . , does something similar. The example above produces a number ; the example below produces a function :

sum . sort . filter (> 0)

Notice that we didn't actually feed a list into this. Instead, we've just created a new function, and we can feed several different lists to that function. For example, you might name this function:

my_function = sum . sort . filter (> 0)

Or you might pass it as an argument to another function:

map (sum . sort . filter (> 0)) my_lists

You can basically use it anywhere that you can use any other sort of function. It's just a quick and readable way of saying "I want to chain these functions together".

From the HaskellWiki page on function composition:

desort = (reverse . sort)

Now desort is a function that sorts a list in reverse. Basically, desort feeds it's arguments into sort , and then feeds the return value from sort into reverse , an returns that. So it sorts it, and then it reverses the sorted list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM