Imperative
int total = 0;
for (int n = 1; n <= 100; n++)
if (n % 2 == 0)
total += n;
Functional
total = sum (filter even [1..100])
Defined with an equation
Prelude> a = 2
Prelude> 5 * a
10
Prelude> b = 10 * a
Prelude> b
20
Prelude> c = b < 100
Prelude> c
True
Values in Haskell are immutable
Defined with an equation, take one or more parameters
double x = 2 * x
Produce single result when applied to arguments
Prelude> double 5
10
Function application can be nested
Prelude> double (double 5)
20
Parameters and arguments are separated by spaces
Prelude> add x y = x + y
Prelude> add 2 5
7
Function application has higher priority than other operators so
f a + b
means (f a) + b
Use parantheses to change order of evaluation, e.g.
f (a + b)
'
)myFunc
,
arg_1
,
x'
,
x''
MyFunc
,
1arg
,
'x
Bool |
Logical values | True and False |
Char |
Single characters | 'a' , 'B' , '1' |
String |
List of Chars |
"abc" , "" , "a" |
Int |
Fixed precision | 1 , -10 , 999 |
Integer |
Arbitrary precision | 99999999999999 |
Float |
Single precision | 1.0 , -0.99 |
Double |
Double precision | 999999999999.9 |
The notation v :: T
indicates
v
has type
T
Prelude> :type True
True :: Bool
Prelude> :t 'a'
'a' :: Char
Prelude> :t "a"
"a" :: [Char]
Every expression has a type, including functions
Prelude> :type not
not :: Bool -> Bool
Prelude> not True
False
Prelude> not False
True
Functions can be declared with a type
Prelude> :{
Prelude| happy :: Bool -> Bool -> Bool
Prelude| happy sunny cold = sunny && not cold
Prelude| :}
Prelude> happy True True
False
Prelude> happy True False
True
If not declared, types are inferred
Prelude> sad sunny cold = not sunny || cold
Prelude> :t sad
sad :: Bool -> Bool -> Bool
Prelude> sad True False
False
Prelude> double x = x * 2
Prelude> :t double
double :: Num a => a -> a
Num a =>
is a polymorphic constraint
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’
Normally written between two arguments (infix)
Prelude> :t (+)
(+) :: Num a => a -> a -> a
Prelude> 2 + 5
7
Prelude> :t (&&)
(&&) :: Bool -> Bool -> Bool
Prelude> True && False
False
Can also be used in prefix notation using brackets
Prelude> (+) 2 5
7
Prelude> (&&) True False
False
Prelude> :t (==)
(==) :: Eq a => a -> a -> Bool
Prelude> 1 == 2
False
Prelude> :t (/=)
(/=) :: Eq a => a -> a -> Bool
Prelude> 1 /= 2
True
Functions can be used in infix notation using backticks
Prelude> :t div
div :: Integral a => a -> a -> a
Prelude> div 10 3
3
Prelude> 10 `div` 3
3
Prelude> 10 `mod` 3
1
Binary subtraction operator and negate
function
Prelude> :t (-)
(-) :: Num a => a -> a -> a
Prelude> 2 - 1
1
Prelude> :t negate
negate :: Num a => a -> a
Prelude> negate 1
-1
Unary minus is syntatic sugar for negate
Prelude> x = -1
Prelude> x
-1
Prelude> y = 2 * (-1)
Prelude> y
-2
Sequences of elements of the same type
Prelude> :t [True,False,True]
[True,False,True] :: [Bool]
Prelude> :t ['a','b','c']
['a','b','c'] :: [Char]
Prelude> :t ["abc","def"]
["abc","def"] :: [[Char]]
Prelude> :t []
[] :: [a]
The type of a list conveys no information about its length; in fact, lists can be infinite!
The cons (:
) and
concatenation (++
) operators
Prelude> :t (:)
(:) :: a -> [a] -> [a]
Prelude> 1 : []
[1]
Prelude> 1 : [2, 3]
[1,2,3]
Prelude> :t (++)
(++) :: [a] -> [a] -> [a]
Prelude> [1] ++ [2]
[1,2]
Prelude> [1,2] ++ [3,4]
[1,2,3,4]
Prelude> [] ++ []
[]
Prelude> head [1,2,3,4,5]
1
Prelude> tail [1,2,3,4,5]
[2,3,4,5]
Prelude> [1,2,3,4,5] !! 2
3
Prelude> take 3 [1,2,3,4,5]
[1,2,3]
Prelude> drop 3 [1,2,3,4,5]
[4,5]
Prelude> length [1,2,3,4,5]
5
Prelude> sum [1,2,3,4,5]
15
Prelude> product [1,2,3,4,5]
120
Prelude> reverse [1,2,3,4,5]
[5,4,3,2,1]
Prelude> filter odd [1,2,3,4,5]
[1,3,5]
Prelude> null [1]
False
Prelude> null []
True
Prelude is a module containing useful definitions and functions, included into all Haskell programs by default
Expressions are not evaluated until results are needed
Prelude> infinity = [1..]
Prelude> take 5 infinity
[1,2,3,4,5]
Prelude> take 10 infinity
[1,2,3,4,5,6,7,8,9,10]
Prelude> sum (take 1000 (filter even infinity))
1001000
Prelude> :t repeat
repeat :: a -> [a]
Prelude> repeatedOnes = repeat 1
Prelude> take 10 repeatedOnes
[1,1,1,1,1,1,1,1,1,1]
It is possible to force the evaluation of an expression, and Haskell libraries often come with strict variants
Finite sequence of elements of possibly different types
Prelude> a = (True, False)
Prelude> :t a
a :: (Bool, Bool)
Prelude> b = (1, "haskell", not, (True, 'a'))
Prelude> :t b
b :: Num a => (a, [Char], Bool -> Bool, (Bool, Char))
Prelude> c = ()
Prelude> :t c
c :: ()
Prelude> d = ("tuple of arity one?")
Prelude> :t d
d :: [Char]
The number of elements in a tuple is called arity; tuples of arity one are not permitted!
Useful functions for tuples of 2 elements (pairs)
Prelude> :t fst
fst :: (a, b) -> a
Prelude> :t snd
snd :: (a, b) -> b
Prelude> fst (1, True)
1
Prelude> snd (1, True)
True