“Funneverstops.
IntroductiontoHaskell
Programminglanguage”
twitter: @rabbitonweb,
github: github.com/rabbitonweb
“Funneverstops.
IntroductiontoHaskell
Programminglanguage”
twitter: @rabbitonweb,
github: github.com/rabbitonweb
FOR SCALA
DEVELOPERS
WhylearnHaskell
???
TherearetwotypesofScaladevelopers:
TherearetwotypesofScaladevelopers:
1)thosewhoarehappytheynolongerprograminJava
TherearetwotypesofScaladevelopers:
1)thosewhoarehappytheynolongerprograminJava
2)ThoseWhoarepissedofftheyarenotyetusinghaskell
TherearetwotypesofScaladevelopers:
1)thosewhoarehappytheynolongerprograminJava
2)ThoseWhoarepissedofftheyarenotyetusinghaskell
Let’s get a bit of that Haskell taste...
WhylearnHaskell?
WhylearnHaskell?
HaskellisPureFunctional
ProgrammingLanguage
WhatisFunctionalProgramming?
❏ no assignment statements
WhatisFunctionalProgramming?
❏ no assignment statements
❏ no variables
WhatisFunctionalProgramming?
❏ no assignment statements
❏ no variables
❏ once given a value, never change
WhatisFunctionalProgramming?
❏ no assignment statements
❏ no variables
❏ once given a value, never change
❏ no side-effects at all
WhatisFunctionalProgramming?
❏ no assignment statements
❏ no variables
❏ once given a value, never change
❏ no side-effects at all
WhatisFunctionalProgramming?
❏ no assignment statements
❏ no variables
❏ once given a value, never change
❏ no side-effects at all
WhatisFunctionalProgramming?
❏ no assignment statements
❏ no variables
❏ once given a value, never change
❏ no side-effects at all
WhatisFunctionalProgramming?
❏ no assignment statements
❏ no variables
❏ once given a value, never change
❏ no side-effects at all
WhatisFunctionalProgramming?
WhatisFunctionalProgramming?
❏ no assignment statements
❏ no variables
❏ once given a value, never change
❏ no side-effects at all
“The functional programmer sounds
rather like a mediæval monk,
denying himself the pleasures of
life in the hope that it will make
him virtuous.”
WhyFunctionalProgrammingMatters?
WhyFunctionalProgrammingMatters?
What procedural programming,
dependency injection, actor
model, microservices and
clean architecture have in
common?
WhyFunctionalProgrammingMatters?
What procedural programming,
dependency injection, actor
model, microservices and
clean architecture have in
common?
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
What procedural programming,
dependency injection, actor
model, microservices and
clean architecture have in
common?
f(input): output
input f(input): output
input f(input): output output
input f(input): output output g(input): output
input f(input): output output g(input): output output
h = g o f
input f(input): output output g(input): output output
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
❏ There is no concept of time
Whatwillthisfunctiondo?
/**
* This function returns a reversed list
* @param list A list to be reversed
* @return A reversed list
*/
def reverse[T](list: List[T]): List[T] = ???
Whatwillthisfunctiondo?
/**
* This function returns a reversed list
* @param list A list to be reversed
* @return A reversed list
*/
def reverse[T](list: List[T]): List[T] = ???
Whatwillthisfunctiondo?
/**
* This function returns a reversed list
* @param list A list to be reversed
* @return A reversed list
def reverse[T](list: List[T]): List[T] = ???
Whatwillthisfunctiondo?
/**
* This function returns a reversed list
* @param list A list to be reversed
def reverse[T](list: List[T]): List[T] = ???
Whatwillthisfunctiondo?
/**
* This function returns a reversed list
def reverse[T](list: List[T]): List[T] = ???
Whatwillthisfunctiondo?
/**
def reverse[T](list: List[T]): List[T] = ???
Whatwillthisfunctiondo?
def reverse[T](list: List[T]): List[T] = ???
Whatwillthisfunctiondo?
def reverse[T](list: List[T]): List[T] = list.sort
Whatwillthisfunctiondo?
Whatwillthisfunctiondo?
def rhrggahaham[A](a: A): A = ???
Whatwillthisfunctiondo?
def rhrggahaham[A](a: A): A = ???
Ifwrittenbyfunctionalprogrammer
Whatwillthisfunctiondo?
def rhrggahaham[A](a: A): A = ???
Whatwillthisfunctiondo?
def rhrggahaham[A](a: A): A = a
Whatwillthisfunctiondo?
def identity[A](a: A): A = a
Whatwillthisfunctiondo?
def rhrggahaham[A](a: A): A = a
Whatwillthisfunctiondo?
def rhrggahaham[A](a: A): A = a
Whatwillthisfunctiondo?
def rhrggahaham[A](a: A): A = a
Whatwillthisfunctiondo?
def rhrggahaham(a: Int): Int = ???
Whatwillthisfunctiondo?
def rhrggahaham(a: Int): Int = ???
Ifwrittenbyfunctionalprogrammer
Whatwillthisfunctiondo?
def rhrggahaham(a: Int): Int = a
a + 10
20
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
❏ There is no concept of time
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
❏ There is no concept of time
❏ We can reason about our code
with ease
def curry
scala> def add(a: Int, b: Int) = a + b
add: (a: Int, b: Int)Int
scala> def add(a: Int, b: Int) = a + b
add: (a: Int, b: Int)Int
scala> val curriedAdd = curry(add)
curriedAdd: Int => (Int => Int) = <function1>
scala> def add(a: Int, b: Int) = a + b
add: (a: Int, b: Int)Int
scala> val curriedAdd = curry(add)
curriedAdd: Int => (Int => Int) = <function1>
scala> val add5 = curriedAdd(5)
scala> add5(7)
res1: Int = 12
def curry
def curry[A,B,C](f: (A, B) => C):
def curry[A,B,C](f: (A, B) => C): (A => (B => C)) =
def curry[A,B,C](f: (A, B) => C): (A => (B => C)) =
(a: A) => ?
def curry[A,B,C](f: (A, B) => C): (A => (B => C)) =
(a: A) => ( ? => ? )
def curry[A,B,C](f: (A, B) => C): (A => (B => C)) =
(a: A) => ( (b: B) => ? )
def curry[A,B,C](f: (A, B) => C): (A => (B => C)) =
(a: A) => ( (b: B) => f(a,b) )
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
❏ There is no concept of time
❏ We can reason about our code
with ease
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
❏ There is no concept of time
❏ We can reason about our code
with ease
❏ Just follow types
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
❏ There is no concept of time
❏ We can reason about our code
with ease
❏ Just follow types
❏ Lazy evaluation
WhyFunctionalProgrammingMatters?
❏ We strive for modularity
❏ There is no concept of time
❏ We can reason about our code
with ease
❏ Just follow types
❏ Lazy evaluation
WhylearnHaskell
???
WhylearnHaskell?
HaskellisPureFunctional
ProgrammingLanguage
WhylearnHaskell?
HaskellisPureFunctional
ProgrammingLanguage
WhylearnHaskell?
HaskellisPureFunctional
ProgrammingLanguage
https://xkcd.com/1312/
World-> (World,A)
World-> (World,A)
"aninteractiveprogramisapurefunctionthattakesthe
current'stateoftheworld'asitsarg.andproducesa
modifiedworldasresult"
World-> (World,A)
“Protip:Don'ttrytotrackreal-worldstateinyourcode.
Insteadtakeitasanargument,sinceonlytheworld
knowswhatstateit'sin.”
World->(World,A)
World->(World,A)
PURE
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
World->(World,A)
IMPURE
World->(World,A)
World->(World,A)
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
= f currentStateOfTheWorld
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
= f currentStateOfTheWorld
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
= f currentStateOfTheWorld
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
= f currentStateOfTheWorld
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
= f currentStateOfTheWorld
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
(newWorld, someValue) = f currentStateOfTheWorld
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
(newWorld, someValue) = f currentStateOfTheWorld
modifyWorldWith newWorld
f
World->(World,A)
currentStateOfTheWorld = stateOfTheWorld
(newWorld, someValue) = f currentStateOfTheWorld
modifyWorldWith newWorld
display someValue
f
JustaLittlebitof
history
HaskellHistoryinanutshell
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
❏ At the FPCA'87 few formed a consensus that an open
standard should be defined for FP languages
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
❏ At the FPCA'87 few formed a consensus that an open
standard should be defined for FP languages
❏ Haskell 1.0 defined in 1990
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
❏ At the FPCA'87 few formed a consensus that an open
standard should be defined for FP languages
❏ Haskell 1.0 defined in 1990
❏ Haskell 98 in late 1997
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
❏ At the FPCA'87 few formed a consensus that an open
standard should be defined for FP languages
❏ Haskell 1.0 defined in 1990
❏ Haskell 98 in late 1997
“(...) intended to specify a stable, minimal, portable
version of the language and an accompanying standard library
for teaching, and as a base for future extensions.”
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
❏ At the FPCA'87 few formed a consensus that an open
standard should be defined for FP languages
❏ Haskell 1.0 defined in 1990
❏ Haskell 98 in late 1997
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
❏ At the FPCA'87 few formed a consensus that an open
standard should be defined for FP languages
❏ Haskell 1.0 defined in 1990
❏ Haskell 98 in late 1997
❏ “The Haskell 98 Report” in 1999
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
❏ At the FPCA'87 few formed a consensus that an open
standard should be defined for FP languages
❏ Haskell 1.0 defined in 1990
❏ Haskell 98 in late 1997
❏ “The Haskell 98 Report” in 1999
❏ “The Haskell 2010 Report” in 2009/2010
HaskellHistoryinanutshell
❏ Miranda released 1985 - de facto FP ‘standard’
❏ At the FPCA'87 few formed a consensus that an open
standard should be defined for FP languages
❏ Haskell 1.0 defined in 1990
❏ Haskell 98 in late 1997
❏ “The Haskell 98 Report” in 1999
❏ “The Haskell 2010 Report” in 2009/2010
❏ Further Haskell evolves rapidly around GHC
Showussomecode
already!
GHC-GlassgowHaskellCompiler
GHC-GlassgowGloriousHaskellCompiler
GHC-GlassgowGloriousHaskellCompiler
❏ > ghci
❏ :t
❏ +set :t
❏ :load
❏ Emacs + Haskell mode
❏ C-c C-b
❏ C-c C-l
FunWithFunctions
FunWithFunctions
helloWorld = “Hello World”
FunWithFunctions
❏ function without parameters is called definition
helloWorld = “Hello World”
FunWithFunctions
❏ function without parameters is called definition
❏ function name must start with small letter
helloWorld = “Hello World”
FunWithFunctions
❏ function without parameters is called definition
❏ function name must start with small letter
> helloWorld
"Hello World"
it :: [Char]
helloWorld = “Hello World”
FunWithFunctions
FunWithFunctions
london u = “London “ ++ u
FunWithFunctions
> :t london
london :: [Char] -> [Char]
london u = “London “ ++ u
FunWithFunctions
> :t london
london :: [Char] -> [Char]
> london "baby"
"london baby"
it :: [Char]
london u = “London “ ++ u
FunWithFunctions
> :t london
london :: [Char] -> [Char]
> london "baby"
"london baby"
it :: [Char]
london :: [Char] -> [Char]
london u = “London “ ++ u
FunWithFunctions
isA c = c == 'A'
FunWithFunctions
isA :: Char -> Bool
isA c = c == 'A'
FunWithFunctions
> isA 'd'
False
> isA 'A'
True
isA :: Char -> Bool
isA c = c == 'A'
FunWithFunctions
FunWithFunctions
prefixMe c str = [c] ++ " " ++ str
FunWithFunctions
> prefixMe '_' "word"
"_ word"
it :: [Char]
prefixMe c str = [c] ++ " " ++ str
FunWithFunctions
> :t prefixMe
prefixMe :: Char -> [Char] -> [Char]
> prefixMe '_' "word"
"_ word"
it :: [Char]
prefixMe c str = [c] ++ " " ++ str
FunWithFunctions
> :t prefixMe
prefixMe :: Char -> ([Char] -> [Char])
> prefixMe '_' "word"
"_ word"
it :: [Char]
prefixMe c str = [c] ++ " " ++ str
FunWithFunctions
FunWithFunctions
answerToEverything = 42
FunWithFunctions
answerToEverything = 42
complexCalc x y z = x * y * z * answerToEverything
FunWithFunctions
> :t complexCalc
complexCalc :: Integer -> Integer -> Integer -> Integer
answerToEverything = 42
complexCalc x y z = x * y * z * answerToEverything
FunWithFunctions
> :t complexCalc
complexCalc :: Integer -> Integer -> Integer -> Integer
complexCalc :: Integer -> (Integer -> (Integer -> Integer))
answerToEverything = 42
complexCalc x y z = x * y * z * answerToEverything
FunWithFunctions
> :t complexCalc
complexCalc :: Integer -> Integer -> Integer -> Integer
complexCalc :: Integer -> (Integer -> (Integer -> Integer))
> complexCalc 10 20 30
answerToEverything = 42
complexCalc x y z = x * y * z * answerToEverything
FunWithFunctions
> :t complexCalc
complexCalc :: Integer -> Integer -> Integer -> Integer
complexCalc :: Integer -> (Integer -> (Integer -> Integer))
> complexCalc 10 20 30
> ((complexCalc 10) 20) 30
answerToEverything = 42
complexCalc x y z = x * y * z * answerToEverything
FunWithTypes
FunWithTypes
❏ We’ve already seen: Char, Integers & Bool
FunWithTypes
❏ We’ve already seen: Char, Integers & Bool
❏ Other build-in types:
FunWithTypes
❏ We’ve already seen: Char, Integers & Bool
❏ Other build-in types:
❏ Int, Float, Doubles
FunWithTypes
❏ We’ve already seen: Char, Integers & Bool
❏ Other build-in types:
❏ Int, Float, Doubles
❏ Tuples
FunWithTypes
❏ We’ve already seen: Char, Integers & Bool
❏ Other build-in types:
❏ Int, Float, Doubles
❏ Tuples
> (False, "Is it?")
it :: (Bool, [Char])
> (10.4, True, "Values", 'Y')
it :: (Double, Bool, [Char], Char)
FunWithTypes
❏ We’ve already seen: Char, Integers & Bool
❏ Other build-in types:
❏ Int, Float, Doubles
❏ Tuples
FunWithTypes
❏ We’ve already seen: Char, Integers & Bool
❏ Other build-in types:
❏ Int, Float, Doubles
❏ Tuples
❏ Lists
> [False, False, True]
it :: [Bool]
> [10, 20, 30]
it :: [Integer]
> ["one", "two", "three"]
it :: [[Char]]
Polymorphic types
Polymorphic types
> length [False, False, True]
3
Polymorphic types
> length [False, False, True]
3
> length [10, 20, 30, 40]
4
Polymorphic types
> length [False, False, True]
3
> length [10, 20, 30, 40]
4
> length ["one", "two", "three"]
3
Polymorphic types
> length [False, False, True]
3
> length [10, 20, 30, 40]
4
> length ["one", "two", "three"]
3
length :: [a] -> Int
Polymorphic types
> length [False, False, True]
3
> length [10, 20, 30, 40]
4
> length ["one", "two", "three"]
3
length :: [a] -> Int
‘a’ is a type variable, which means that length can be
applied to list of any type
List101
List101
numbers = [1, 3, 5, 7]
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
null numbers -> False
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
null numbers -> False
head numbers -> 1
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
null numbers -> False
head numbers -> 1
tail numbers -> [3, 5, 7]
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
null numbers -> False
head numbers -> 1
tail numbers -> [3, 5, 7]
init numbers -> [1, 3, 5]
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
null numbers -> False
head numbers -> 1
tail numbers -> [3, 5, 7]
init numbers -> [1, 3, 5]
last numbers -> 7
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
null numbers -> False
head numbers -> 1
tail numbers -> [3, 5, 7]
init numbers -> [1, 3, 5]
last numbers -> 7
drop 2 numbers -> [5, 7]
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
null numbers -> False
head numbers -> 1
tail numbers -> [3, 5, 7]
init numbers -> [1, 3, 5]
last numbers -> 7
drop 2 numbers -> [5, 7]
take 2 numbers -> [1, 3]
List101
numbers = [1, 3, 5, 7]
numbers !! 2 -> 5
null numbers -> False
head numbers -> 1
tail numbers -> [3, 5, 7]
init numbers -> [1, 3, 5]
last numbers -> 7
drop 2 numbers -> [5, 7]
take 2 numbers -> [1, 3]
elem 5 numbers -> True
List101
List101
[1..6] -> [1, 2, 3, 4, 5, 6]
List101
[1..6] -> [1, 2, 3, 4, 5, 6]
[1,3,.., 20] -> [1,3,5,7,9,11,13,15,17,19]
List101
[1..6] -> [1, 2, 3, 4, 5, 6]
[1,3,.., 20] -> [1,3,5,7,9,11,13,15,17,19]
[1..] -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
List101
[1..6] -> [1, 2, 3, 4, 5, 6]
[1,3,.., 20] -> [1,3,5,7,9,11,13,15,17,19]
take 5 [1..] -> [1, 2, 3, 4, 5]
List101
[1..6] -> [1, 2, 3, 4, 5, 6]
[1,3,.., 20] -> [1,3,5,7,9,11,13,15,17,19]
take 5 [1..] -> [1, 2, 3, 4, 5]
(cycle [0, 1]) -> [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,..
List101
[1..6] -> [1, 2, 3, 4, 5, 6]
[1,3,.., 20] -> [1,3,5,7,9,11,13,15,17,19]
take 5 [1..] -> [1, 2, 3, 4, 5]
take 6 (cycle [0, 1]) -> [0,1,0,1,0,1]
List101
[1..6] -> [1, 2, 3, 4, 5, 6]
[1,3,.., 20] -> [1,3,5,7,9,11,13,15,17,19]
take 5 [1..] -> [1, 2, 3, 4, 5]
take 6 (cycle [0, 1]) -> [0,1,0,1,0,1]
take 3 (repeat 2) -> [2, 2, 2]
List101
List101
[2 ^ x | x <- [1..5]] -> [2,4,8,16,32]
List101
[2 ^ x | x <- [1..5]] -> [2,4,8,16,32]
take 7 [2 ^ x | x <- [1..]] -> [2,4,8,16,32,64,128]
List101
[2 ^ x | x <- [1..5]] -> [2,4,8,16,32]
take 7 [2 ^ x | x <- [1..]] -> [2,4,8,16,32,64,128]
[(x,y) | x <- [1..5], y <- [1..5]] -> [(1,1),(1,2),(1,3), ...
List101
[2 ^ x | x <- [1..5]] -> [2,4,8,16,32]
take 7 [2 ^ x | x <- [1..]] -> [2,4,8,16,32,64,128]
[(x,y) | x <- [1..5], y <- [1..5]] -> [(1,1),(1,2),(1,3), …
[(x,y) | x <- [1..2], y <- [x..2]] -> [(1,1),(1,2),(2,2)]
List101
[2 ^ x | x <- [1..5]] -> [2,4,8,16,32]
take 7 [2 ^ x | x <- [1..]] -> [2,4,8,16,32,64,128]
[(x,y) | x <- [1..5], y <- [1..5]] -> [(1,1),(1,2),(1,3), ...
[(x,y) | x <- [1..2], y <- [x..2]] -> [(1,1),(1,2),(2,2)]
[x | x <- [1..7], x `mod` 2 == 0] -> [2, 4, 6]
List101
[2 ^ x | x <- [1..5]] -> [2,4,8,16,32]
take 7 [2 ^ x | x <- [1..]] -> [2,4,8,16,32,64,128]
[(x,y) | x <- [1..5], y <- [1..5]] -> [(1,1),(1,2),(1,3), ...
[(x,y) | x <- [1..2], y <- [x..2]] -> [(1,1),(1,2),(2,2)]
[x | x <- [1..7], x `mod` 2 == 0] -> [2, 4, 6]
zip "abc" [1,2,3] -> [('a',1),('b',2),('c',3)]
List101
[2 ^ x | x <- [1..5]] -> [2,4,8,16,32]
take 7 [2 ^ x | x <- [1..]] -> [2,4,8,16,32,64,128]
[(x,y) | x <- [1..5], y <- [1..5]] -> [(1,1),(1,2),(1,3), ...
[(x,y) | x <- [1..2], y <- [x..2]] -> [(1,1),(1,2),(2,2)]
[x | x <- [1..7], x `mod` 2 == 0] -> [2, 4, 6]
zip "abc" [1,2,3] -> [('a',1),('b',2),('c',3)]
zip "abc" (cycle [0,1]) -> [('a',0),('b',1),('c',0)]
List101
[2 ^ x | x <- [1..5]] -> [2,4,8,16,32]
take 7 [2 ^ x | x <- [1..]] -> [2,4,8,16,32,64,128]
[(x,y) | x <- [1..5], y <- [1..5]] -> [(1,1),(1,2),(1,3), ...
[(x,y) | x <- [1..2], y <- [x..2]] -> [(1,1),(1,2),(2,2)]
[x | x <- [1..7], x `mod` 2 == 0] -> [2, 4, 6]
zip "abc" [1,2,3] -> [('a',1),('b',2),('c',3)]
zip "abc" (cycle [0,1]) -> [('a',0),('b',1),('c',0)]
zipWith (+) [1,2,3] [4,5,6] -> [5,7,9]
Classes
Classes
caseclassFoo(...)???
Classes
caseclassFoo(...)???
No,notthoseclasses.Typeclasses.
TypeClasses
Type class is a set of types which support certain
collection of functions defined by the class.
TypeClasses
❏ Eq
TypeClasses
❏ Eq
(==) :: a -> a -> Bool; (/=) :: a -> a -> Bool
TypeClasses
❏ Eq
(==) :: a -> a -> Bool; (/=) :: a -> a -> Bool
❏ Ord
TypeClasses
❏ Eq
(==) :: a -> a -> Bool; (/=) :: a -> a -> Bool
❏ Ord
< , <= , > , >= :: a -> a -> Bool; min , max :: a -> a -> a
TypeClasses
❏ Eq
(==) :: a -> a -> Bool; (/=) :: a -> a -> Bool
❏ Ord
< , <= , > , >= :: a -> a -> Bool; min , max :: a -> a -> a
❏ Show
TypeClasses
❏ Eq
(==) :: a -> a -> Bool; (/=) :: a -> a -> Bool
❏ Ord
< , <= , > , >= :: a -> a -> Bool; min , max :: a -> a -> a
❏ Show
show :: a -> String
TypeClasses
❏ Eq
(==) :: a -> a -> Bool; (/=) :: a -> a -> Bool
❏ Ord
< , <= , > , >= :: a -> a -> Bool; min , max :: a -> a -> a
❏ Show
show :: a -> String
❏ Read
TypeClasses
❏ Eq
(==) :: a -> a -> Bool; (/=) :: a -> a -> Bool
❏ Ord
< , <= , > , >= :: a -> a -> Bool; min , max :: a -> a -> a
❏ Show
show :: a -> String
❏ Read
read :: String -> a
TypeClasses
> 10 == 20
False
TypeClasses
> 10 == 20
False
> 10 < 20
True
TypeClasses
> 10 == 20
False
> 10 < 20
True
> show 1 ++ " is a number"
"1 is a number"
TypeClasses
> 10 == 20
False
> 10 < 20
True
> show 1 ++ " is a number"
"1 is a number"
> read "5" + 10
15
TypeClasses
> 10 == 20
False
> 10 < 20
True
> show 1 ++ " is a number"
"1 is a number"
> read "5" + 10
15
> read "5"
<interactive>:85:1:
No instance for (Read a0) arising from a use of `read'
*Main> read "5" :: Integer 5 it :: Integer
TypeClasses
> 10 == 20
False
> 10 < 20
True
> show 1 ++ " is a number"
"1 is a number"
> read "5" + 10
15
> read "5" :: Integer
5
Typeclasses&classconstraints
add a b = a + b
Typeclasses&classconstraints
add :: Num a => a -> a -> a
add a b = a + b
Typeclasses&classconstraints
add :: Num a => a -> a -> a
add a b = a + b
add 10 20
Typeclasses&classconstraints
add :: Num a => a -> a -> a
add a b = a + b
add 10 20
add 5.0 7.0
Typeclasses&classconstraints
add :: Num a => a -> a -> a
add a b = a + b
add 10 20
add 5.0 7.0
weirdo n d str = (n + 2, d / 2.0, str ++ "!!")
Typeclasses&classconstraints
add :: Num a => a -> a -> a
add a b = a + b
add 10 20
add 5.0 7.0
weirdo :: (Fractional t1, Num t) =>
t -> t1 -> [Char] -> (t, t1, [Char])
weirdo n d str = (n + 2, d / 2.0, str ++ "!!")
Typeclasses&classconstraints
add :: Num a => a -> a -> a
add a b = a + b
add 10 20
add 5.0 7.0
weirdo :: (Fractional t1, Num t) =>
t -> t1 -> [Char] -> (t, t1, [Char])
weirdo n d str = (n + 2, d / 2.0, str ++ "!!")
weirdo 7 7.0 “kuku”
Typeclasses&classconstraints
add :: Num a => a -> a -> a
add a b = a + b
add 10 20
add 5.0 7.0
weirdo :: (Fractional t1, Num t) =>
t -> t1 -> [Char] -> (t, t1, [Char])
weirdo n d str = (n + 2, d / 2.0, str ++ "!!")
weirdo 7 7.0 “kuku”
weirdo 7.0 5.0 “mono”
FunWithFunctions,Part2
sum :: Num a => [a] -> a
FunWithFunctions,Part2
sum :: Num a => [a] -> a
sum list = if null list then 0
else 1 + sum (tail list)
FunWithFunctions,Part2
sum :: Num a => [a] -> a
FunWithFunctions,Part2
sum :: Num a => [a] -> a
sum [] = 0
FunWithFunctions,Part2
sum :: Num a => [a] -> a
sum [] = 0
sum x:xs = 1 + sum xs
FunWithFunctions,Part2
programmingLanguage :: [Char] -> [Char]
FunWithFunctions,Part2
programmingLanguage :: [Char] -> [Char]
programmingLanguage "Scala" = "Good"
FunWithFunctions,Part2
programmingLanguage :: [Char] -> [Char]
programmingLanguage "Scala" = "Good"
programmingLanguage "Haskell" = "Even better!"
FunWithFunctions,Part2
programmingLanguage :: [Char] -> [Char]
programmingLanguage "Scala" = "Good"
programmingLanguage "Haskell" = "Even better!"
programmingLanguage other = "Meh..." ++ other ++ ", pf.."
FunWithFunctions,Part2
first :: (a, b, c) -> a
first (x, _, _) = x
second :: (a, b, c) -> b
second (_, y, _) = y
third :: (a, b, c) -> c
third (_, _, z) = z
FunWithFunctions,Part2
rankMe :: (Num a, Ord a) => a -> [Char]
FunWithFunctions,Part2
rankMe :: (Num a, Ord a) => a -> [Char]
rankMe lines
FunWithFunctions,Part2
rankMe :: (Num a, Ord a) => a -> [Char]
rankMe lines
| lines > 100 = "Senior"
FunWithFunctions,Part2
rankMe :: (Num a, Ord a) => a -> [Char]
rankMe lines
| lines > 100 = "Senior"
| lines > 30 = "Regular"
FunWithFunctions,Part2
rankMe :: (Num a, Ord a) => a -> [Char]
rankMe lines
| lines > 100 = "Senior"
| lines > 30 = "Regular"
| lines >= 0 = "Junior"
FunWithFunctions,Part2
rankMe :: (Num a, Ord a) => a -> [Char]
rankMe lines
| lines > 100 = "Senior"
| lines > 30 = "Regular"
| lines >= 0 = "Junior"
| lines < 0 = "Congrats! You are a true Hacker!"
FunWithFunctions,Part2
rankMe :: (Num a, Ord a) => a -> a -> a -> [Char]
rankMe added deleted modified
| lines > 100 = "Senior"
| lines > 30 = "Regular"
| lines >= 0 = "Junior"
| lines < 0 = "Congrats! You are a true Hacker!"
FunWithFunctions,Part2
rankMe :: (Num a, Ord a) => a -> a -> a -> [Char]
rankMe added deleted modified
| lines > 100 = "Senior"
| lines > 30 = "Regular"
| lines >= 0 = "Junior"
| lines < 0 = "Congrats! You are a true Hacker!"
where lines = added - deleted
Creatingnewtypes
Creatingnewtypes-aliasing
Creatingnewtypes-aliasing
type String = [Char]
Creatingnewtypes-aliasing
type String = [Char]
type Point = (Int, Int)
Creatingnewtypes-aliasing
type String = [Char]
type Point = (Int, Int)
type Parser a = String -> (a, String)
Creatingnewtypes
Creatingnewtypes-Datadeclarations
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
bootup :: OS -> [Char]
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
bootup :: OS -> [Char]
bootup Unix = "Up and running"
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
bootup :: OS -> [Char]
bootup Unix = "Up and running"
bootup Linux = "Well, I was actually never down..."
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
bootup :: OS -> [Char]
bootup Unix = "Up and running"
bootup Linux = "Well, I was actually never down..."
bootup OSX = "Non-sufficient Starbucks coffee, please refill"
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
bootup :: OS -> [Char]
bootup Unix = "Up and running"
bootup Linux = "Well, I was actually never down..."
bootup OSX = "Non-sufficient Starbucks coffee, please refill"
bootup Windows = "Upgrading to Windows 10, this should take a
second.."
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
class Bootable a where
boot :: a -> [Char]
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
class Bootable a where
boot :: a -> [Char]
instance Bootable OS where
boot Unix = "Up and running"
boot Linux = "Well, I was actually never down..."
boot OSX = "Non-sufficient Starbucks coffee, please refill"
boot Windows = "Upgrading to Windows 10, this should take a
second.."
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
instance Eq OS where
Unix == Unix = True
Linux == Linux = True
OSX == OSX = True
Windows == Windows = True
_ == _ = False
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
instance Eq OS where
Unix == Unix = True
Linux == Linux = True
OSX == OSX = True
Windows == Windows = True
_ == _ = False
> Unix == Windows
False
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
instance Show OS where
show Unix = "Unix"
show Linux = "Linux"
show OSX = "OSX"
show Windows = "Windows"
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
instance Show OS where
show Unix = "Unix"
show Linux = "Linux"
show OSX = "OSX"
show Windows = "Windows"
> show Unix
"Unix"
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
deriving (Eq, Ord, Show, Read)
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
deriving (Eq, Ord, Show, Read)
> Windows == Unix
False
Creatingnewtypes-Datadeclarations
data OS = Windows | OSX | Linux | Unix
deriving (Eq, Ord, Show, Read)
> Windows == Unix
False
> show Windows
"Windows"
> read "Windows"::OS
Windows
> Linux > Windows
True
Creatingnewtypes-Datadeclarations
data Shape = Circle Float | Rect Float Float
deriving Show
> Circle 10
Circle 10.0
data Option a = Nothing | Some a
deriving Show
> Some “one”
Some “one”
Creatingnewtypes-Datadeclarations
data Shape = Circle Float | Rect Float Float
deriving Show
> Circle 10
Circle 10.0
data Option a = Nothing | Some a
deriving Show
> Some “one”
Some “one”
Expressiveness
Quicksort
Quicksort
qs [] = []
Quicksort
qs [] = []
qs (x : xs) = qs smaller ++ [x] ++ qs larger
Quicksort
qs [] = []
qs (x : xs) = qs smaller ++ [x] ++ qs larger
where smaller = [a | a <- xs, a <= x]
larger = [b | b <- xs, b > x]
Quicksort
qs [] = []
qs (x : xs) = qs smaller ++ [x] ++ qs larger
where smaller = [a | a <- xs, a <= x]
larger = [b | b <- xs, b > x]
> qs [3,7,1,9,3,10]
[1,3,3,7,9,10]
FizzBuzz
FizzBuzz
1,
FizzBuzz
1,2
FizzBuzz
1,2,Fizz,
FizzBuzz
1,2,Fizz,4,Buzz,
FizzBuzz
1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz,11,12,13,
FizzBuzz
1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz,11,12,13,14,FizzBuzz,..
FizzBuzz
FizzBuzz
fizzes = cycle ["", "", "fizz"]
buzzes = cycle ["", "", "", "", "buzz"]
FizzBuzz
fizzes = cycle ["", "", "fizz"]
buzzes = cycle ["", "", "", "", "buzz"]
pattern = zipWith (++) fizzes buzzes
FizzBuzz
fizzes = cycle ["", "", "fizz"]
buzzes = cycle ["", "", "", "", "buzz"]
pattern = zipWith (++) fizzes buzzes
> take 16 pattern
["","","fizz","","buzz","fizz","","","fizz","buzz","","
fizz","","","fizzbuzz",""]
FizzBuzz
fizzes = cycle ["", "", "fizz"]
buzzes = cycle ["", "", "", "", "buzz"]
pattern = zipWith (++) fizzes buzzes
FizzBuzz
fizzes = cycle ["", "", "fizz"]
buzzes = cycle ["", "", "", "", "buzz"]
pattern = zipWith (++) fizzes buzzes
fizzbuzz = zipWith combine pattern [1..]
where combine word number =
if null word then show number else word
FizzBuzz
fizzes = cycle ["", "", "fizz"]
buzzes = cycle ["", "", "", "", "buzz"]
pattern = zipWith (++) fizzes buzzes
fizzbuzz = zipWith combine pattern [1..]
where combine word number =
> take 16 pattern if null word then show number else word
["1","2","fizz","4","buzz","fizz","7","8","fizz","buzz","
11","fizz","13","14","fizzbuzz","16"]
Whatnext?
Whatnext?
Whatnext?
1. Read “Why Functional Programming Matters paper”
Whatnext?
1. Read “Why Functional Programming Matters paper”
2. Try to implement examples from that paper using Haskell
Whatnext?
1. Read “Why Functional Programming Matters paper”
2. Try to implement examples from that paper using Haskell
3. Sign for FP101x
Whatnext?
1. Read “Why Functional Programming Matters paper”
2. Try to implement examples from that paper using Haskell
3. Sign for FP101x
https://courses.edx.org/courses/course-v1:
DelftX+FP101x+3T2015/courseware/79633017711e44c9878df4f33701
4766/
Whatnext?
1. Read “Why Functional Programming Matters paper”
2. Try to implement examples from that paper using Haskell
3. Sign for FP101x
4. Try out Frege (Haskell on the JVM)
Whatnext?
1. Read “Why Functional Programming Matters paper”
2. Try to implement examples from that paper using Haskell
3. Sign for FP101x
4. Try out Frege (Haskell on the JVM)
https://github.com/Frege/frege
PawelSzulc
PawelSzulc
twitter: @rabbitonweb,
PawelSzulc
twitter: @rabbitonweb,
github: github.com/rabbitonweb
PawelSzulc
twitter: @rabbitonweb,
github: github.com/rabbitonweb
blog: rabbitonweb.com
PawelSzulc
THANKYOUVERYMUCH
twitter: @rabbitonweb,
github: github.com/rabbitonweb
blog: rabbitonweb.com

Fun never stops. introduction to haskell programming language