Types that contain one or more type variables
Prelude> :t head
head :: [a] -> a
Prelude> head [1..10]
1
Prelude> head [True,False,True]
True
Prelude> head "haskell"
'h'
Prelude> head ["haskell","is","cool"]
"haskell"
Type variables must begin with lower-case letters
and are usually named
a
, b
, c
...
tail :: [a] -> [a]
take :: Int -> [a] -> [a]
filter :: (a -> Bool) -> [a] -> [a]
map :: (a -> b) -> [a] -> [b]
replicate :: Int -> a -> [a]
(!!) :: [a] -> Int -> a
fst :: (a, b) -> a
snd :: (a, b) -> b
C a =>
indicates that the type variable
a
must implement the C
typeclass
Prelude> :t (>)
(>) :: Ord a => a -> a -> Bool
Prelude> 2 > 1
True
Prelude> 'b' > 'a'
True
Prelude> "Haskell is great" > "Haskell is cool"
True
Prelude> [2,1,0] > [2,0,5]
True
Prelude> even > odd
No instance for (Ord (Integer -> Bool)) arising from a use of ‘>’
Prelude> '2' > 1
No instance for (Num Char) arising from the literal ‘1’
Prelude> :info Ord
class Eq a => Ord a where
compare :: a -> a -> Ordering
(<) :: a -> a -> Bool
(<=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(>=) :: a -> a -> Bool
max :: a -> a -> a
min :: a -> a -> a
{-# MINIMAL compare | (<=) #-}
instance Ord Int -- Defined in ‘GHC.Classes’
instance Ord Float -- Defined in ‘GHC.Classes’
instance Ord Double -- Defined in ‘GHC.Classes’
instance Ord Char -- Defined in ‘GHC.Classes’
instance Ord Bool -- Defined in ‘GHC.Classes’
...
Prelude> :info Eq
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
{-# MINIMAL (==) | (/=) #-}
instance Eq Int -- Defined in ‘GHC.Classes’
instance Eq Float -- Defined in ‘GHC.Classes’
instance Eq Double -- Defined in ‘GHC.Classes’
instance Eq Char -- Defined in ‘GHC.Classes’
instance Eq Bool -- Defined in ‘GHC.Classes’
...
Prelude> :info Num
class Num a where
(+) :: a -> a -> a
(-) :: a -> a -> a
(*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
{-# MINIMAL (+), (*), abs, signum, fromInteger, (negate | (-)) #-}
instance Num Word -- Defined in ‘GHC.Num’
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Int -- Defined in ‘GHC.Num’
instance Num Float -- Defined in ‘GHC.Float’
instance Num Double -- Defined in ‘GHC.Float’
...
Prelude> :info Show
class Show a where
showsPrec :: Int -> a -> ShowS
show :: a -> String
showList :: [a] -> ShowS
{-# MINIMAL showsPrec | show #-} -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show Int -- Defined in ‘GHC.Show’
instance Show Char -- Defined in ‘GHC.Show’
...
Prelude> show 1
"1"
Prelude> [1..10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> odd
No instance for (Show (Integer -> Bool))
Haskell infers types as generic as possible
Prelude> add x y = x + y
Prelude> :t add
add :: Num a => a -> a -> a
Prelude> add 2 5
7
Prelude> add 2.0 5.0
7.0
Prelude> :{
Prelude| addInts :: Int -> Int -> Int
Prelude| addInts x y = x + y
Prelude| :}
Prelude> addInts 2.0 5.0
No instance for (Fractional Int) arising from the literal ‘2.0’
A partially-applied function is also a function
Prelude> add x y = x + y
Prelude> :t add
add :: Num a => a -> a -> a
Prelude> :t add 1
add 1 :: Num a => a -> a
Prelude> addOne = add 1
Prelude> addOne 5
6
In Haskell, f :: a -> b -> c
is actually
f :: a -> (b -> c)
Functions can take functions as arguments,
and return functions as their result
Prelude> :t filter
filter :: (a -> Bool) -> [a] -> [a]
Prelude> :t (>)
(>) :: Ord a => a -> a -> Bool
Prelude> filter (>10) [1,12,5,8,26,10,7,15]
[12,26,15]
Prelude> twice f x = f (f x)
Prelude> :t twice
twice :: (t -> t) -> t -> t
Prelude> twice (*2) 5
20
Prelude> twice reverse [1..10]
[1,2,3,4,5,6,7,8,9,10]
Currying is a form of higher-order functions
Prelude> :{
Prelude| add :: Num a => a -> (a -> a)
Prelude| add x = (+) x
Prelude| :}
Prelude> :t add
add :: Num a => a -> a -> a
map
applies a function to all elements of a list
Prelude> :t map
map :: (a -> b) -> [a] -> [b]
Prelude> map (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
Prelude> :t even
even :: Integral a => a -> Bool
Prelude> map even [1..10]
[False,True,False,True,False,True,False,True,False,True]
Prelude> map reverse ["haskell","is","cool"]
["lleksah","si","looc"]
Prelude> reverse ["haskell","is","cool"]
["cool","is","haskell"]
even n :: Integral a => a -> Bool
even n = n `mod` 2 == 0
splitAt :: Int -> [a] -> ([a], [a])
splitAt n xs = (take n xs, drop n xs)
recip :: Fractional a => a -> a
recip n = 1 / n
Prelude> even 9
False
Prelude> even 10
True
Prelude> splitAt 3 [1..10]
([1,2,3],[4,5,6,7,8,9,10])
Prelude> splitAt 7 "haskellcurry"
("haskell","curry")
Prelude> recip 10
0.1
A condition and two results of the same type
abs :: Int -> Int
abs n = if n >= 0 then n else -n
signum :: Int -> Int
signum n = if n < 0 then -1 else if n == 0 then 0 else 1
The else branch must always exist!
Sequence of logical expressions, with their own results
abs n | n >= 0 = n
| otherwise = -n
signum n
| n < 0 = -1
| n == 0 = 0
| otherwise = 1
otherwise
matches anything and is a
safe way to handle all other cases - and avoid an error!
Match argument values against patterns
not :: Bool -> Bool
not True = False
not False = True
(&&) :: Bool -> Bool -> Bool
True && True = True
True && False = False
False && True = False
False && False = False
A non-exhaustive pattern can cause an exception
Underscores match anything; variables bind to values
(&&) :: Bool -> Bool -> Bool
True && True = True
_ && _ = False
(&&) :: Bool -> Bool -> Bool
True && b = b
False && _ = False
(&&) :: Bool -> Bool -> Bool
b && b = b
_ && _ = False
Values may not be evaluated due to lazy evaluation
alpha :: [Int] -> Bool
alpha [0,_,_] = True
alpha _ = False
alpha' :: [Int] -> Bool
alpha' (0:_) = True
alpha' _ = False
Prelude> alpha [0,1,2]
True
Prelude> alpha [0,1]
False
Prelude> alpha' [0]
True
Prelude> alpha' [0..]
True
head :: [a] -> a
head (x:_) = x
tail :: [a] -> [a]
tail (_:xs) -> xs
dropThird (x1:x2:_:xs) = x1 : x2 : xs
dropThird xs = xs
Prelude> dropThird [1..10]
[1,2,4,5,6,7,8,9,10]
Prelude> 1:2:3:4:5:6:[]
[1,2,3,4,5,6]
fst :: (a,b) -> a
fst (x,_) = x
snd :: (a,b) -> b
snd (_,x) = x
third :: (a,b,c) -> c
third (_,_,x) = x
Prelude> third (1, True, "haskell")
"haskell"
Prelude> third ('a', even, (False, 10.0))
(False,10.0)
Bound to a scope (indicated by indentation)
qsort [] = []
qsort (x:xs) = qsort smaller ++ [x] ++ qsort larger
where smaller = filter (<= x) xs
larger = filter (> x) xs
dist (x1,y1) (x2,y2) = sqrt (dx + dy)
where
dx = (x1 - x2) ^ 2
dy = (y1 - y2) ^ 2
Do not use tabs - the compiler will complain!
Can be used wherever expressions are allowed
dist (x1,y1) (x2,y2) =
let dx = (x1 - x2) ^ 2
dy = (y1 - y2) ^ 2
in sqrt (dx + dy)
The symbol \
stands for the Greek
letter λ
\ x -> 2 * x
Prelude> (\x y -> x + y) 2 5
7
Prelude> filter (\x -> x `mod` 7 == 0) [1..100]
[7,14,21,28,35,42,49,56,63,70,77,84,91,98]
Prelude> records = [(1,True,"haskell"), (2,False,"curry")]
Prelude> fmap (\(x,_,y) -> (10 * x,head y)) records
[(10,'h'),(20,'c')]