module HigherOrder where
import Prelude hiding ((++))
Lets define two functions ...
plus1 :: Int -> Int
plus1 x = x + 1
minus1 :: Int -> Int
minus1 x = x - 1
... we can manipulate functions like ordinary data
aPairOfFuns = (plus1, minus1)
aListOfFuns = [plus1, minus1, plus1, minus1]
aBigListoFuns = replicate 10 plus1 ++ replicate 5 minus1
ghci> :type aBigListoFuns
aBigListoFuns :: [Int -> Int]
Take functions as inputs
Return functions as outputs
doTwice f x = f (f x)
Takes as input
f
x
and returns as output
x
to f
two timesdoTwice f x = f (f x)
Lets run it,
ghc> doTwice plus1 10
12
ghc> doTwice minus1 100
98
doTwice f x = f (f x)
doTwice plus1 10
== {- unfold doTwice -}
plus1 (plus1 10)
== {- unfold plus1 -}
plus1 (10 + 1)
== {- unfold plus1 -}
(10 + 1) + 1
== {- old-school arithmetic -}
12
Instead of writing plus1
, plus2
, plus3
...
plusn :: Int -> (Int -> Int)
plusn n = f
where f x = x + n
We can now use the above to write
plus2 = plusn 2
plus10 = plusn 10
minus20 = plusn (-20) -- why the parens?
which can be used ...
ghc> plus10 100
110
ghc> minus20 1000
980
You can derive the result by substitutions...
plus10 100
== {- unfold plus10 -}
(plusn 10) 100
== {- unfold plusn -}
f 100
where f x = x + 10
== {- unfold f -}
100 + 10
== {- arithmetic -}
110
-
and ->
are operators
-
is an operator on integers->
is an operator on types-
and ->
are operators
-
is Left-Associative2 - 1 - 1 == (2 - 1) - 1 == 0
->
is Right-AssociativeInt -> Int -> Int == Int -> (Int -> Int)
plus :: Int -> Int -> Int
plus n x = n + x
Here, plus
actually has type (Haskell hides ugly parens)
plus :: Int -> (Int -> Int)
So plus
n
, returns a function that ...
x
, returns the sum of x
and n
plus :: Int -> Int -> Int
plus n x = n + x
plus
plus
plus100 = plus 100
x
100 + x
ghci> plus100 566
666
ex1 = doTwice (plus 99)
What is the type of ex1
?
What is the value of ex1 100
?
Haskell lets you create functions that have no name
plus 1000
Very useful for functions-that-are-used-once
Create nameless functions with lambda (just a \
)
\ param -> body
For example, a function that returns 1
more than its input
\x -> x + 1
We can call it, just like any other function
ghci> (\x -> x + 1) 100
101
ghci> doTwice (\x -> x + 1) 100
102
Lambda-functions are just values ... so you can name them
plus42 = \x -> x + 42
Lambda-functions are just values ... so you can name them
In general, an old-school equation-style function definition
f x1 x2 ... xn = e
is equivalent to the lambda-style definition
f = \x1 -> \x2 -> ... xn -> e
which can be shortened to
f = \x1 x2 ... xn -> e
To improve readability Haskell lets you use some functions as infix
Any function whose name is surrounded in backticks
Any function defined with parens
Instead of plus 2 10
you can write
ghci> 2 `plus` 10
12
or, instead of clone "thirty" 3
you can say
ghci> "thirty" `clone` 3
["thirty", "thirty", "thirty"]
For some heavily used functions, convenient to skip the ticks
-- What does this function do?
(++) [] ys = ys
(++) (x:xs) ys = x : (xs ++ ys)
which lets us write
ex2 = [1,2,3] ++ [4,5,6]
Quiz: What is the value of ex2
?
To further improve readability, partially apply infix operators
ghci> doTwice (+1) 0
2
:
the list cons operator, is also infix, so...
ex3 = doTwice (0:) [7]
Quiz: what is the value of ex3
?