2024-03-14 13:59:07 +00:00
|
|
|
{- Contents
|
2024-03-14 17:02:18 +00:00
|
|
|
A short introduction to Haskell;
|
2024-03-14 13:59:07 +00:00
|
|
|
On how to create simple functions.
|
|
|
|
-}
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
-- Elementary Functions
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
|
|
|
{- General Syntax for functions
|
|
|
|
* Input on the left, output on the right.
|
|
|
|
* Functions also have a type: input type on the left
|
2024-03-14 17:02:18 +00:00
|
|
|
side, output type on the right side, arrow in-between.
|
2024-03-14 13:59:07 +00:00
|
|
|
-}
|
|
|
|
inc1 :: Integer -> Integer
|
|
|
|
inc1 n = n + 1
|
|
|
|
|
|
|
|
{- Lambda notation
|
|
|
|
Everything can also be written on the right side (lambda
|
|
|
|
notation). In fact, `inc1` is just syntactic sugar for
|
|
|
|
`inc2`.
|
|
|
|
-}
|
|
|
|
inc2 :: Integer -> Integer
|
|
|
|
inc2 = \n -> n + 1
|
|
|
|
|
|
|
|
{- Function application
|
|
|
|
To apply a function, write the function to the left of
|
|
|
|
the input/argument (no brackets needed).
|
|
|
|
-}
|
|
|
|
two :: Integer
|
|
|
|
two = inc1 1
|
|
|
|
|
|
|
|
someGreeting :: String -> String
|
|
|
|
someGreeting person = "Hello " ++ person
|
|
|
|
|
|
|
|
|
|
|
|
{- Exercise
|
|
|
|
Define a function `square`, that squares the given input
|
|
|
|
and write down its type. Define the same function using
|
|
|
|
the lambda notation.
|
|
|
|
-}
|
|
|
|
square :: Integer -> Integer
|
2024-03-14 17:02:18 +00:00
|
|
|
square x = x ^ 2
|
|
|
|
|
|
|
|
-- >>> square 3
|
|
|
|
-- 9
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
squareLambda :: Integer -> Integer
|
2024-03-14 17:02:18 +00:00
|
|
|
squareLambda = \x -> x ^ 2
|
|
|
|
|
|
|
|
-- >>> squareLambda 4
|
|
|
|
-- 16
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
-- Functions of Several Variables
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
|
|
|
{- Tupled Inputs
|
|
|
|
'addTupled' is binary function, its output depends on
|
|
|
|
two separate integers.
|
|
|
|
-}
|
|
|
|
addTupled :: (Integer, Integer) -> Integer
|
|
|
|
addTupled (x, y) = x + y
|
|
|
|
|
|
|
|
{-
|
|
|
|
'avg3Tupled' is a function that depends on three input
|
|
|
|
variables.
|
|
|
|
-}
|
|
|
|
avg3Tupled :: (Float, Float, Float) -> Float
|
|
|
|
avg3Tupled ( x, y, z ) = (x + y + z) / 3
|
|
|
|
|
|
|
|
{- Evaluating with Tuples
|
|
|
|
We evaluate a function of several variables by providing
|
2024-03-14 17:02:18 +00:00
|
|
|
values *for each* input variable.
|
2024-03-14 13:59:07 +00:00
|
|
|
-}
|
|
|
|
four :: Float
|
|
|
|
four = avg3Tupled ( 3, 4, 5 )
|
|
|
|
|
|
|
|
{-
|
|
|
|
If we want to evaluate a multivariable function before
|
|
|
|
we have all inputs ready, we have to properly
|
|
|
|
parametrize it. We can do this with curried functions.
|
|
|
|
More on that later!
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
|
|
{- A Curried Function
|
|
|
|
'add' is the parametrized (a.k.a curried) version of
|
|
|
|
`add`. It is a function that returns a (unary) function.
|
|
|
|
|
|
|
|
Note that the following three lines are equivalent
|
|
|
|
declarations:
|
|
|
|
|
|
|
|
'add = \x -> \y -> x + y'
|
|
|
|
|
|
|
|
'add x = \y -> x + y'
|
|
|
|
|
|
|
|
'add x y = x + y'
|
|
|
|
|
|
|
|
Also note that the parenthesis are not needed in the
|
|
|
|
declaration of the type of 'add'.
|
|
|
|
-}
|
|
|
|
add :: Int -> (Int -> Int)
|
|
|
|
add n m = n + m
|
|
|
|
|
|
|
|
|
|
|
|
{- Partial Application
|
|
|
|
'add3' is the function that adds '3' to any given input.
|
|
|
|
Thanks to currying, we can realize 'add3' as a special
|
|
|
|
case of 'add'. Thanks to partial application, this
|
|
|
|
corresponds to a single function call.
|
|
|
|
-}
|
|
|
|
add3 :: Int -> Int
|
|
|
|
add3 = add 3
|
|
|
|
|
2024-03-14 17:02:18 +00:00
|
|
|
-- >>> add3 7
|
|
|
|
-- 10
|
|
|
|
|
2024-03-14 13:59:07 +00:00
|
|
|
{- Exercise
|
|
|
|
Declare a curried version of the function 'avg3Tupled'
|
|
|
|
as a lambda term.
|
|
|
|
-}
|
|
|
|
avg3 :: Float -> Float -> Float -> Float
|
2024-03-14 17:02:18 +00:00
|
|
|
avg3 = \x -> \y -> \z -> avg3Tupled (x, y, z)
|
|
|
|
|
|
|
|
-- >>> avg3 7 9 2
|
|
|
|
-- 6.0
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
{- Exercise
|
|
|
|
use the binary function '(++)' that concatenates strings
|
|
|
|
to specify a function that prepends "=> " to any given
|
|
|
|
input string. Use partial application
|
|
|
|
-}
|
|
|
|
prepArrow :: String -> String
|
2024-03-14 17:02:18 +00:00
|
|
|
prepArrow = (++) "=> "
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
-- When calling this
|
|
|
|
-- > prepArrow "foo"
|
|
|
|
-- It should output the following
|
|
|
|
-- '=> foo'
|
|
|
|
|
2024-03-14 17:02:18 +00:00
|
|
|
-- >>> prepArrow "foo"
|
|
|
|
-- "=> foo"
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
-- Higher Order Functions
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
|
|
|
{- Function as Input
|
|
|
|
'apply' is a function that accepts a function as input
|
|
|
|
(and applies it to the remaining input)
|
|
|
|
-}
|
|
|
|
apply :: (a -> b) -> a -> b
|
|
|
|
apply f x = f x
|
|
|
|
|
|
|
|
{- Function as Input and Output
|
|
|
|
'twice' is a function that accepts and returns a
|
|
|
|
function.
|
|
|
|
-}
|
|
|
|
twice :: (a -> a) -> (a -> a)
|
|
|
|
twice f x = f (f x)
|
|
|
|
-- twice f = f . f -- Alternatively use this syntax
|
|
|
|
|
|
|
|
{- Exercise
|
|
|
|
Write a function `thrice` that applies a function three
|
|
|
|
times.
|
|
|
|
-}
|
|
|
|
thrice :: (a -> a) -> a -> a
|
2024-03-14 17:02:18 +00:00
|
|
|
thrice f x = f (twice f x)
|
|
|
|
|
|
|
|
-- >>> thrice (\x -> x + 1) 10
|
|
|
|
-- 13
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
{- Exercise
|
|
|
|
Write a function 'compose' that accepts two functions
|
|
|
|
and applies them to a given argument in order.
|
|
|
|
-}
|
|
|
|
compose :: (a -> b) -> (b -> c) -> a -> c
|
2024-03-14 17:02:18 +00:00
|
|
|
compose f g x = g (f x)
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
{- Exercise
|
2024-03-14 17:02:18 +00:00
|
|
|
reimplement 'twice' and 'thrice' as an application
|
2024-03-14 13:59:07 +00:00
|
|
|
of the function 'compose'.
|
|
|
|
-}
|
|
|
|
twiceByComp :: (a -> a) -> a -> a
|
2024-03-14 17:02:18 +00:00
|
|
|
twiceByComp f = compose f f
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
thriceByComp :: (a -> a) -> a -> a
|
2024-03-14 17:02:18 +00:00
|
|
|
thriceByComp f = compose f (twiceByComp f)
|
2024-03-14 13:59:07 +00:00
|
|
|
|
|
|
|
{- List map
|
|
|
|
A often used higher function is ``mapping'' of lists.
|
|
|
|
This function will apply a function (given as an
|
|
|
|
argument) to every element in a list (also given as an
|
2024-03-14 17:02:18 +00:00
|
|
|
argument) and return a new list containing the changed
|
2024-03-14 13:59:07 +00:00
|
|
|
values. There are a lot of other functions to work
|
|
|
|
with lists (and similar types). We will learn about
|
|
|
|
these functions later.
|
|
|
|
-}
|
|
|
|
mapping :: [Integer]
|
|
|
|
mapping = map (\n -> n + 1) [1, 2, 3]
|
|
|
|
|
|
|
|
{-| Exercise
|
|
|
|
greet all friends using 'friends', 'map' and
|
|
|
|
'greeting'.
|
|
|
|
-}
|
|
|
|
friends :: [String]
|
|
|
|
friends =
|
|
|
|
[ "Peter"
|
|
|
|
, "Nina"
|
|
|
|
, "Janosh"
|
|
|
|
, "Reto"
|
|
|
|
, "Adal"
|
|
|
|
, "Sara"
|
|
|
|
]
|
|
|
|
|
|
|
|
greeting :: String -> String
|
|
|
|
greeting person = "Hello " ++ person
|
|
|
|
|
|
|
|
greetFriends :: [String]
|
2024-03-14 17:02:18 +00:00
|
|
|
greetFriends = map greeting friends
|
2024-03-14 13:59:07 +00:00
|
|
|
|
2024-03-14 17:02:18 +00:00
|
|
|
-- >>> greetFriends
|
|
|
|
-- ["Hello Peter","Hello Nina","Hello Janosh","Hello Reto","Hello Adal","Hello Sara"]
|