I have been documenting the concepts and apis of the programming language Haskel. This document has examples of various constructs of the Haskel programming language. It is a live document. Until I complete the contents of [0], I will be updating this document.
function declaration
f x = x + 2 # f(x) = x + 2
conditional
abs x = if x < 0 (-1) * x else x # an if should always have an else
list
list contains element of the same type.
let myList = [1,2,3]
strings are considered as lists too. "abc" is equivalent to ['a', 'b', 'c']
append to last [slower operation if the first list is big]
myList ++ [5, 6]
append single element to first
7 : myList
[1, 2, 3] is equivalent to 1:2:3:[]
access list element
myList !! 2 # access 2nd element of the list
list comparison
rule: 2 lists can be compared if the elements can be compared. Nonempty list is greater than empty list. element by element is done from start of the list until a match found or one/both of the lists ends.
operator: <, <=, >=, >, ==
a = [1,2,3], b = [4,5,6]
a < b # False
list of list
a = [[], [1,2,3], [4]]
list operations
[<head><......tail......>]
[<.......init.....><last>]
operations does not have side effect meaning they don't modify the list.
head [1,2,3,4,5] #1
tail [1,2,3,4,5] #[2,3,4,5]
init [1,2,3,4,5] #[1,2,3,4]
last [1,2,3,4,5] #5
length [1,2,3] # 3
null [] # True
null [1] # false
reverse [1,2,3] # [3,2,1]
take 1 [7,2,3] # [7]
drop 1 [7,2,3] #[2,3]
maximum [2, 4, 5, 1] # 5
minimum [2, 3, 1, 5] # 1
sum [1, 2, 3] # 6
product [1, 2, 3, 4] # 24
elem 7 [1, 6, 7] # True, 7 belongs to the list
[1..5] #[1,2,3,4,5]
['a'..'d'] # ['a', 'b', 'c', 'd']
[5,4..1] #[5,4,3,2,1]
cycle[1,2,3] #produces infinite list [1,2,3,1,2,3,1,2,3,...infinite]
repeat 5 # [5,5,5,5,5,5,5....infinite size]
repeat [1] # [[1], [1], [1], [1], [1] ... infinite size]
replicate 4 2 # [2, 2, 2, 2]
list comprehension
[x * 2 | x <- [0..5]] # all x * 2 s such that x belongs to the set [0, 1, 2, 3, 4, 5]
[x * 2 | x <- [0..5], x > 5] # multiple predicate
evenOdd xs = [ if x `mod` 2 == 0 then 0 else 1 | x <- xs ] # function evenOdd takes a list xs and returns a list of 0s and 1s
usage: evenOdd [0..10] # [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
[x + y | x <- [0..5], y <- [0..3]] # for all x and y in the sets, generates a list that has the value x + y
length' ls = sum [1 | _ <- ls] # generate a list that has 1 for each element of ls, then sum up all the 1s
Tuple
stores heterogenous typed elements. size is fixed.
(1, 1.1, 'a', "saif")
tuple types are defined by the number of elements in it. a list can hold only same typed elements. thus,
[(1,2), (2, 3), (1,2,3)] causes ERROR
[(1, 2), ('a', 1)] also causes ERROR
Pairs
(1, 3)
fst (1,3) # 1
snd (1,3) # 3
zip ['a', 'b', 'c'] ['x', 'y', 'z'] # [('a','x'),('b','y'),('c','z')]
zip "abc" [1..] # [('a',1),('b',2),('c',3)] notice how only 3 elements are taken from the infinite set
function declaration
f x = x + 2 # f(x) = x + 2
conditional
abs x = if x < 0 (-1) * x else x # an if should always have an else
list
list contains element of the same type.
let myList = [1,2,3]
strings are considered as lists too. "abc" is equivalent to ['a', 'b', 'c']
append to last [slower operation if the first list is big]
myList ++ [5, 6]
append single element to first
7 : myList
[1, 2, 3] is equivalent to 1:2:3:[]
access list element
myList !! 2 # access 2nd element of the list
list comparison
rule: 2 lists can be compared if the elements can be compared. Nonempty list is greater than empty list. element by element is done from start of the list until a match found or one/both of the lists ends.
operator: <, <=, >=, >, ==
a = [1,2,3], b = [4,5,6]
a < b # False
list of list
a = [[], [1,2,3], [4]]
list operations
[<head><......tail......>]
[<.......init.....><last>]
operations does not have side effect meaning they don't modify the list.
head [1,2,3,4,5] #1
tail [1,2,3,4,5] #[2,3,4,5]
init [1,2,3,4,5] #[1,2,3,4]
last [1,2,3,4,5] #5
length [1,2,3] # 3
null [] # True
null [1] # false
reverse [1,2,3] # [3,2,1]
take 1 [7,2,3] # [7]
drop 1 [7,2,3] #[2,3]
maximum [2, 4, 5, 1] # 5
minimum [2, 3, 1, 5] # 1
sum [1, 2, 3] # 6
product [1, 2, 3, 4] # 24
elem 7 [1, 6, 7] # True, 7 belongs to the list
[1..5] #[1,2,3,4,5]
['a'..'d'] # ['a', 'b', 'c', 'd']
[5,4..1] #[5,4,3,2,1]
cycle[1,2,3] #produces infinite list [1,2,3,1,2,3,1,2,3,...infinite]
repeat 5 # [5,5,5,5,5,5,5....infinite size]
repeat [1] # [[1], [1], [1], [1], [1] ... infinite size]
replicate 4 2 # [2, 2, 2, 2]
list comprehension
[x * 2 | x <- [0..5]] # all x * 2 s such that x belongs to the set [0, 1, 2, 3, 4, 5]
[x * 2 | x <- [0..5], x > 5] # multiple predicate
evenOdd xs = [ if x `mod` 2 == 0 then 0 else 1 | x <- xs ] # function evenOdd takes a list xs and returns a list of 0s and 1s
usage: evenOdd [0..10] # [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
[x + y | x <- [0..5], y <- [0..3]] # for all x and y in the sets, generates a list that has the value x + y
length' ls = sum [1 | _ <- ls] # generate a list that has 1 for each element of ls, then sum up all the 1s
Tuple
stores heterogenous typed elements. size is fixed.
(1, 1.1, 'a', "saif")
tuple types are defined by the number of elements in it. a list can hold only same typed elements. thus,
[(1,2), (2, 3), (1,2,3)] causes ERROR
[(1, 2), ('a', 1)] also causes ERROR
Pairs
(1, 3)
fst (1,3) # 1
snd (1,3) # 3
zip ['a', 'b', 'c'] ['x', 'y', 'z'] # [('a','x'),('b','y'),('c','z')]
zip "abc" [1..] # [('a',1),('b',2),('c',3)] notice how only 3 elements are taken from the infinite set
## Type ##
Type is fixed.
ghci command :t shows type of a variable or function.
function type
sum :: Int -> Int -> Int
sum a b = a + b
common types
Int : bounded by underlying system
Integer : unbounded
Float : real number with single precision
Double : real number with double precision
Bool : boolean type
Char : a Unicode character
Type Class
A type class encloses one or more types.
A type can be member of one more type classes.
ghci command. :t (==)
(==) :: (Eq a) => a -> a -> Bool
How to read. (==) takes 2 argument of type class Eq and returns a Bool type.
Eq
applicable function: ==, /= (not equal)
Ord
values of Ord type can be sorted.
functions to apply : >, >=, <, <=.
comparator function returns GT, LT or EQ.
Show
the value can be presented as a string.
function to apply on this type: show # show 3 => "3"
Read
from string, raw type can be formed
applicable function: read
ex: add (read "3") + 3 # 6
read function need enough hint to know which raw type to produce. for example,
this does not work, read "3"
but read "3" + 3 works, because read knows "3" to be converted to Int
the following example works similar to type casting (according to me)
read "3" :: Int # specifically specify we need 3 to be Int.
more examples:
read "[1, 2, 3]" :: [Int] # [1,2,3]
read "(2, 'a')" :: (Int , Char) # (2, 'a')
[read "True", True, False, True]
Enum
sequentially enumerable values.
applicable functions: succ, pred
Bounded
has an upper and lower bound
Num
values act like numbers
Floating
applicable functions: sin cos
Enclosing type: Float, Double
Integral
enclosing type: Int, Integer
## Syntax in Functions ##
Pattern matching: choosing a function based on input parameters. Pattern matching works very similar to if else construct.
citizen :: String -> String
citizen "BD" = "Bangladeshi"
citizen "USA" = "American"
citizen x = "Unknown citizen"
line 0, is function input and output type declaration. line 1, says what to do if input = "BD", so on and so forth.
can be used to define base case.
fibonacci :: Int -> Int
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci n = fibonacci(n-1) + fibonacci(n-2)
If the pattern matching does not contain all the possibilities of input, interpreter will throw an exception.
vector_add :: (Double, Double) -> (Double, Double) -> (Double, Double)
vector_add a b = (fst a + fst b, snd a + snd b)
another way to write
vector_add (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
Usage of '_'
fst' :: (a, b, c) -> a
fst' (a, _, _) = a
head' :: [a] -> a
head' (a:_) = a
As pattern break up input in parts, also gives a way to access the whole. can be applied on list only.
shead :: [Int] -> Int
shead whole@(frst : rest) = frst
Guards
bmiTell :: Double -> String
bmiTell bmi
| bmi <= 18.5 = "underweight"
| bmi <= 25.0 = "normal wieght"
| bmi <= 30.0 = "fat"
| otherwise = "unhealthy fat"
guard syntax | boolean-expression = expression-to-be-evaluated
where
clause. provides variable like functionality of imperative programming language.
bmiTell w h
| bmi <= skinny = "you are fine"
| bmi <= fat = "you are not fine"
where bmi = w / h ^ 2
skinny = 18.5
fat = 23.5
forming tuple and accessing it
initials :: String -> String -> String
initials first last = [f] ++ "." ++ [l] ++ "."
where (f:_) = first
(l:_) = last
where to pattern match
desList :: [a] -> String
desList ls = "the list is " ++ check ls
where check [] = "empty"
check [x] = "singleton"
check xs = "a longer list"
Let
let lets you create an expression that generates a value. let are local in scope.
cylinder :: Double -> Double -> Double
cylinder r h =
let sideArea = 2 * pi * r * h
topArea = pi * r ^ 2
in sideArea + 2 * topArea
pattern: let <variable binding> in <expression>
let square x = x * x in (square 2, square 3, square 4)
list comprehension
calcBMI xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi > 25.0]
the value bound through let is visible before '|' and after the let
Case expression
syntax:
case expression of pattern -> result
pattern -> result
pattern -> result
pattern -> result
example:
sum' :: [Int] -> Int
sum' xs = case xs of [] -> error "empty list"
_ -> sum xs
case can be used inside a function too.
describeList ::[a] -> String
describeList ls = "The list is " ++ case ls of [] -> "empty"
[x] -> "singleton"
xs -> "a longer list"
Type is fixed.
ghci command :t shows type of a variable or function.
function type
sum :: Int -> Int -> Int
sum a b = a + b
common types
Int : bounded by underlying system
Integer : unbounded
Float : real number with single precision
Double : real number with double precision
Bool : boolean type
Char : a Unicode character
Type Class
A type class encloses one or more types.
A type can be member of one more type classes.
ghci command. :t (==)
(==) :: (Eq a) => a -> a -> Bool
How to read. (==) takes 2 argument of type class Eq and returns a Bool type.
Eq
applicable function: ==, /= (not equal)
Ord
values of Ord type can be sorted.
functions to apply : >, >=, <, <=.
comparator function returns GT, LT or EQ.
Show
the value can be presented as a string.
function to apply on this type: show # show 3 => "3"
Read
from string, raw type can be formed
applicable function: read
ex: add (read "3") + 3 # 6
read function need enough hint to know which raw type to produce. for example,
this does not work, read "3"
but read "3" + 3 works, because read knows "3" to be converted to Int
the following example works similar to type casting (according to me)
read "3" :: Int # specifically specify we need 3 to be Int.
more examples:
read "[1, 2, 3]" :: [Int] # [1,2,3]
read "(2, 'a')" :: (Int , Char) # (2, 'a')
[read "True", True, False, True]
Enum
sequentially enumerable values.
applicable functions: succ, pred
Bounded
has an upper and lower bound
Num
values act like numbers
Floating
applicable functions: sin cos
Enclosing type: Float, Double
Integral
enclosing type: Int, Integer
## Syntax in Functions ##
Pattern matching: choosing a function based on input parameters. Pattern matching works very similar to if else construct.
citizen :: String -> String
citizen "BD" = "Bangladeshi"
citizen "USA" = "American"
citizen x = "Unknown citizen"
line 0, is function input and output type declaration. line 1, says what to do if input = "BD", so on and so forth.
can be used to define base case.
fibonacci :: Int -> Int
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci n = fibonacci(n-1) + fibonacci(n-2)
If the pattern matching does not contain all the possibilities of input, interpreter will throw an exception.
vector_add :: (Double, Double) -> (Double, Double) -> (Double, Double)
vector_add a b = (fst a + fst b, snd a + snd b)
another way to write
vector_add (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
Usage of '_'
fst' :: (a, b, c) -> a
fst' (a, _, _) = a
head' :: [a] -> a
head' (a:_) = a
As pattern break up input in parts, also gives a way to access the whole. can be applied on list only.
shead :: [Int] -> Int
shead whole@(frst : rest) = frst
Guards
bmiTell :: Double -> String
bmiTell bmi
| bmi <= 18.5 = "underweight"
| bmi <= 25.0 = "normal wieght"
| bmi <= 30.0 = "fat"
| otherwise = "unhealthy fat"
guard syntax | boolean-expression = expression-to-be-evaluated
where
clause. provides variable like functionality of imperative programming language.
bmiTell w h
| bmi <= skinny = "you are fine"
| bmi <= fat = "you are not fine"
where bmi = w / h ^ 2
skinny = 18.5
fat = 23.5
forming tuple and accessing it
initials :: String -> String -> String
initials first last = [f] ++ "." ++ [l] ++ "."
where (f:_) = first
(l:_) = last
where to pattern match
desList :: [a] -> String
desList ls = "the list is " ++ check ls
where check [] = "empty"
check [x] = "singleton"
check xs = "a longer list"
Let
let lets you create an expression that generates a value. let are local in scope.
cylinder :: Double -> Double -> Double
cylinder r h =
let sideArea = 2 * pi * r * h
topArea = pi * r ^ 2
in sideArea + 2 * topArea
pattern: let <variable binding> in <expression>
let square x = x * x in (square 2, square 3, square 4)
list comprehension
calcBMI xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi > 25.0]
the value bound through let is visible before '|' and after the let
Case expression
syntax:
case expression of pattern -> result
pattern -> result
pattern -> result
pattern -> result
example:
sum' :: [Int] -> Int
sum' xs = case xs of [] -> error "empty list"
_ -> sum xs
case can be used inside a function too.
describeList ::[a] -> String
describeList ls = "The list is " ++ case ls of [] -> "empty"
[x] -> "singleton"
xs -> "a longer list"
Reference:
[0] http://learnyouahaskell.com/
No comments:
Post a Comment