Tuesday, May 21, 2013

HASKELL FUNCTION COMPOSITION

HASKELL FUNCTION COMPOSITION

REVISED: Friday, February 9, 2024




Haskell function composition.

I. HASKELL FUNCTION COMPOSITION

There are two main operations we can do with function values: apply them, and compose them. Haskell's laziness gives us compositionality.

The nesting of two or more functions to form a single new function is known as composition.

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

Read as f of g is the composition of f with g.

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.

The primary purpose of the Haskell function composition . dot operator is to chain functions of the same type. It lets us tie the output of whatever appears on the right of the dot operator to the input of whatever appears on the left of the dot operator as long as they are of the same type.

The programming style of function composition, is called "pointfree" style, which means the arguments to the function are omitted. In many cases this makes for clearer code. Function composition is a common Haskell idiom. It is very common for functional programmers to write functions as a composition of other functions of the same type, never mentioning the actual arguments they will be applied to.

Pointfree style is often referred to as "pointless" style.

Composition is associative; for example, when more than two numbers are added or multiplied, the result remains the same, irrespective of how they are grouped.

EXAMPLE 1

λx.(3 + 4 * x) `div` 3
=
\x -> (3 + 4 * x) `div` 3

Prelude>  let y x = (3 + 4 * x) `div` 3
y :: Integral a => a -> a
Prelude>

Prelude>  y 3
5
it :: Integral a => a
Prelude>

Prelude>  let y x = (`div` 3) (3 + 4 * x)
y :: Integral a => a -> a
Prelude>

Prelude>  y 3
5
it :: Integral a => a
Prelude>  

Prelude> let y = (`div` 3) . (+ 3) . (* 4)
y :: Integral c => c -> c
Prelude>

Prelude>  y 3
5
it :: Integral c => c
Prelude>  

Step 1:
(* 4) -- Means 3 * 4
12

Step 2:
(+ 3) . (* 4)  -- Means 12 + 3
15

Step 3:
(`div` 3)  -- Means 15 `div` 3
5

EXAMPLE 2


Prelude>  let y = take 3 (reverse (filter even [1..10]))  -- Using ( ) instead of $
y :: Integral a => [a]
Prelude>

Prelude>  y
[10,8,6]
it :: Integral a => [a]
Prelude>  

Prelude>  let y = take 3 . reverse . filter even [1..10]  -- With no $ [1..10] 

<interactive>:33:28:
    Couldn't match expected type ‘a -> [a1]’ with actual type ‘[a0]’
    Relevant bindings include
      y :: a -> [a1] (bound at <interactive>:33:5)
    Possible cause: ‘filter’ is applied to too many arguments
    In the second argument of ‘(.)’, namely ‘filter even [1 .. 10]’
    In the second argument of ‘(.)’, namely
      ‘reverse . filter even [1 .. 10]’
Prelude>  

The dot operator expects its second argument to be a function of one argument, not a list.

Prelude>  :type (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
Prelude> 

Prelude>  :info (.)
(.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in `GHC.Base'
infixr 9 .  -- Priority of 9.
Prelude>   

Function application has priority of 10, while function composition has a lower priority of 9. Therefore, we need the $ operator to allow function composition to evaluate first.

Prelude>  let y = take 3 . reverse . filter even $ [1..10]
y :: Integral a => [a]
Prelude>

Prelude>  y
[10,8,6]
it :: Integral a => [a]
Prelude> 

Step 1:
Prelude> filter even $ [1..10]
[2,4,6,8,10]
Prelude>

Step 2:
Prelude> reverse [2,4,6,8,10]
[10,8,6,4,2]
Prelude>

Step 3:
Prelude> take 3 [10,8,6,4,2]
[10,8,6]
Prelude>

II. CONCLUSION

In this tutorial, you have seen examples of  the associative nature of Haskell function composition.

III. REFERENCES

Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.

Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.

Goerzen, J. & O'Sullivan, B. &  Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.

Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.

Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.

Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.