Joseph Haugh
University of New Mexico
Q: What is a type?
A: Collection of related values
Q: What is a typeclass?
A: Collection of related types
Q: What are typeclasses similar to in Java?
A: Interfaces
Q: How are typeclasses more powerful?
A: Many typeclasses can be used to constrain 1 type argument
Q: Can you name a typeclass we have seen so far?
A: Eq
, Ord
, Show
, Read
, Num
, Integral
, Fractional
The easiest function to define is a function defined from existing functions
Test if a given integer is even
even :: Integral a => a -> Bool
even n = n `mod` 2 == 0
Split a list at the nth element
splitAt :: Int -> [a] -> ([a], [a])
splitAt n xs = (take n xs, drop n xs)
abs :: Int -> Int
abs n = if n >= 0 then n else -n
-- Can this be improved?
greaterThan10 :: Int -> Bool
greaterThan10 n = if n > 10 then True else False
abs :: Int -> Int
abs n
| n >= 0 = n
| otherwise = -n
greaterThan10 :: Int -> Bool
greaterThan10 n
| n > 10 = True
| otherwise = False
not :: Bool -> Bool
not True = False
not False = True
(||) :: Bool -> Bool -> Bool
False || False = False
_ || _ = True
-- Does this work?
(||) :: Bool -> Bool -> Bool
_ || _ = True
False || False = False
(||) :: Bool -> Bool -> Bool
True || _ = True
False || b = b
fst :: (a, b) -> a
fst (x, _) = x
snd :: (a, b) -> b
snd (_, y) = y
addTuple :: (Int, Int) -> Int
addTuple (x, y) = x + y
null :: [a] -> Bool
null [] = True
null _ = False
inOrder :: Ord a => [a] -> Bool
inOrder [] = True
inOrder [_] = True
inOrder [x,y] = x <= y
inOrder [x,y,z] = x <= y <= z
-- This obviously needs recursion! We will come back to this.
firstIsOne :: [Int] -> Bool
firstIsOne (1:_) = True
firstIsOne _ = False
[1,2,3]
)(:)
The list [1,2,3]
can be destructed as follows:
[1,2,3]
= { list notation}
1 : [2,3]
= { list notation}
1 : (2 : [3])
= { list notation}
1 : (2 : (3 : []))
(\argument -> expression)
\x -> x + 1
Ordinary functions can also be written in terms of lambdas
add :: Int -> Int -> Int
add x y = x + y
add :: Int -> Int -> Int
add = \x -> (\y -> x + y)
Lambdas can also use _
to ignore their arguments
const :: a -> b -> a
const x _ = x
const :: a -> b -> a
const = \x -> \_ -> x
Lambdas find the most use in higher order functions
We haven’t seen a higher order function yet, but we will soon
One of the most used is the map
function
map
applies a function to every element of a list
add1All :: [Int] -> [Int]
add1All xs = map (\x -> x + 1) xs
> add1All [1,2,3]
[2,3,4]
In that last example it seems tedious to create a lambda just to add 1
What if we could just give 1 to the +
operator and then have it still take its other argument?
We can!
add1All :: [Int] -> [Int]
add1All xs = map (+1) xs
This is called an operator section
(+1)
is equivalent to \x -> x + 1
(1+)
is equivalent to \x -> 1 + x
subtract1All :: [Int] -> [Int]
subtract1All xs = map (-1) xs
> subtract1All [1,2,3]
[0,1,2]
subtractFrom1All :: [Int] -> [Int]
subtractFrom1All xs = map (1-) xs
> subtractFrom1All [1,2,3]
[0,-1,-2]
(!!)
halfAll :: [Int] -> [Int]
that halves every element of a list using map with: