Haskell 101 (Version 1 (July 18, 2012)) Juan Pedro Villa Isaza
Haskell 101: Contents Introduction Tutorial Homework Bibliography
Haskell 101: Contents Introduction Tutorial Homework Bibliography
Haskell 101: Introduction Haskell is fun, and that s what it s all about! Miran Lipovača
Haskell 101: Introduction Even if Haskell seems strange to you at first, don t give up. Learning Haskell is almost like learning to program for the first time all over again. It s fun, and it forces you to think differently. Miran Lipovača
Haskell 101: Introduction Haskell is a deep language; we think that learning it is a hugely rewarding experience. Novelty. Power. Enjoyment. Bryan O Sullivan, John Goerzen, and Don Stewart
Haskell 101: Introduction Haskell is a purely functional programming language. You tell the computer what stuff is. The factorial of a number is the product of every integer from 1 to that number. This operation can be expressed as a function: ghci> let factorial n = product [1..n] You can t set a variable to one value and then set it to something else later on. A function has no side effects. The only thing a function can do is calculate something and return the result. Referential transparency: If a function is called twice with the same parameters, it s guaranteed to return the same result both times.
Haskell 101: Introduction Haskell has strong types. ghci> let x = 1 :: Int ghci> let y = 1 :: Double ghci> x + y Couldn t match expected type... Haskell has static types. ghci> True && "False" Couldn t match expected type... Haskell s combination of strong and static typing makes it impossible for type errors to occur at runtime.
Haskell 101: Introduction Haskell has type inference. ghci> let factorial n = product [1..n] ghci> :type factorial factorial :: (Num t, Enum t) => t -> t Haskell is lazy. ghci> True length [1..] > 0 True Haskell is elegant and concise. qsort :: (Ord a) => [a] -> [a] qsort [] = [] qsort (x:xs) = qsort (filter (<= x) xs) ++ [x] ++ qsort (filter (> x) xs) Haskell is novel, powerful, and fun.
Haskell GHC (The Glasgow Haskell Compiler) The Glasgow Haskell Compiler is a state-of-the-art, open source, compiler and interactive environment for the functional language Haskell. GHC has two main components: GHCi (ghci) is an interactive interpreter and debugger. GHC (ghc) is an optimizing compiler. The Glasgow Haskell Compiler (GHC). www.haskell.org/ghc
Haskell 101: Introduction Try Haskell! tryhaskell.org
Haskell 101: Introduction The Haskell platform Haskell: batteries included. The Haskell platform is the easiest way to get started with Haskell. Comprehensive, robust, cutting edge. The Haskell platform: hackage.haskell.org/platform The Glasgow Haskell Compiler (GHC): www.haskell.org/ghc
Haskell 101: Introduction Emacs Emacs is a text editor, and more. Emacs: www.gnu.org/software/emacs haskell-mode: github.com/haskell/haskell-mode
Haskell 101: Introduction The Haskell community The Haskell Communities and Activities Report. Haskell in industry. Haskell in education. Haskell in research. Haskell and mathematics. Planet Haskell, The Monad.Reader.... Haskell. www.haskell.org
Haskell 101: Introduction Examples: Frag
Haskell 101: Introduction Examples: Monadius
Haskell 101: Introduction Agda, Darcs, and xmonad Agda is a dependently typed functional programming language and a proof assistant. wiki.portal.chalmers.se/agda Darcs is a free, open source code management system. darcs.net xmonad is a dynamically tiling X11 window manager that is written and configured in Haskell. xmonad.org
Haskell 101: Introduction Examples: xmonad xmonad is a window manager that is written and configured in Haskell. In a normal window manager, you spend half your time aligning and searching for windows. xmonad makes work easier, by automating this.
Haskell 101: Introduction Examples: xmonad e
Haskell 101: Introduction Links (1) Haskell: www.haskell.org
Haskell 101: Introduction Links (2) Download Haskell: hackage.haskell.org/platform
Haskell 101: Contents Introduction Tutorial Homework Bibliography
Hello, world! (1) $ ghci... Prelude> Prelude> "Hello, world!" "Hello, world!" Prelude> putstrln "Hello, world!" Hello, world! Prelude> :quit... $
Hello, world! (2) $ cd Examples/ $ emacs hello-world.hs &... $ cat hello-world.hs main :: IO () main = putstrln "Hello, world!" $ ghc hello-world.hs... $./hello-world Hello, world! $
Factorial (1) $ cd Examples/ $ emacs Factorial.hs... $ cat Factorial.hs module Factorial where factorial :: Integral a => a -> a factorial n = product [1..n]
Factorial (2) $ cd Examples/ $ emacs Factorial.hs... $ cat Factorial.hs module Factorial where factorial :: Integral a => a -> a factorial 0 = 1 factorial n = n * factorial (n - 1)
Factorial (3) $ cd Examples/ $ emacs Factorial.hs... $ cat Factorial.hs module Factorial where factorial :: Integral a => a -> a factorial n n == 0 = 1 otherwise = n * factorial (n - 1)
Factorial (4) $ cd Examples/... $ ghci... Prelude> :load Factorial.hs... *Factorial> factorial 42 1405006117752879898543142606244511569936384000000000 *Factorial> :quit... $
Prelude> :set prompt "ghci> " Examples (Basic arithmetic) ghci> 16 + 18 34 ghci> 11 * 6 66 ghci> (-) 2010 1922 88 ghci> 9 / 8 1.125
Examples (The order of operations) ghci> (34 * 88) - 2991 1 ghci> 34 * 88-2991 1 ghci> 34 * (88-2991) -98702 Examples (Negative numbers) ghci> 9 * -8 Precedence parsing error ghci> 9 * (-8) -72
Examples (Boolean algebra) ghci> True && False False ghci> False True True ghci> not (False && True) True Examples (Equality and inequality) ghci> 5 == 5 True ghci> "hello" /= "hello" False
ghci> :set +t Examples (Mathematical constants) ghci> pi 3.141592653589793 it :: Double ghci> e... Not in scope: e ghci> exp 1 2.718281828459045 it :: Double ghci> :unset +t
Examples (Functions) ghci> succ 18 19 ghci> min 16 18 + max 6 11 + 5 32 ghci> succ 2 * 10 30 ghci> succ (2 * 10) 21 ghci> div 10 2 5 ghci> 10 div 2 5
Basics: Types ghci> :t f f :: Char ghci> :t "foo" "foo" :: [Char] Common types Int Integers 1, 2, 3, 4,... Integer Integers 1, 2, 3, 4,... Float Floating point numbers 1.0, 2.0, 3.0, 4.0,... Double Floating point numbers 1.0, 2.0, 3.0, 4.0,... Bool Booleans True, False Char Unicode characters a, b, c, d,... In Haskell, every expression and function has a type.
Basics: Lists Examples ghci> ["David","Roger"] ["David","Roger"] ghci> [True,False,"True"] Couldn t match expected type... ghci> "Hello" ++ ", " ++ "world!" "Hello, world!" ghci> [ h, e ] ++ [ l, l, o ] "hello" ghci> [1..5] ++ [5,4..1] [1,2,3,4,5,5,4,3,2,1]
Basics: Lists Examples ghci> a :[ b.. z ] "abcdefghijklmnopqrstuvwxyz" ghci> 1:2:3:4:5:[] [1,2,3,4,5] ghci> [ a.. y ]: z Couldn t match expected type... ghci> [[1..5],[5,4..1]] [[1,2,3,4,5],[5,4,3,2,1]]
Basics: Lists Examples ghci> [3,4,2] < [3,4,3] True ghci> [3,4,2] < [2,4] False ghci> [3,2,1] > [2,10,100] True ghci> "gilmour" > "waters" False ghci> [3,4,2] == [3,4,2] True ghci> [[],[]] == [[],[],[]] False
Basics: Lists Examples (List operations) ghci> head [1..5] ghci> last [1..5] 1 5 ghci> init [1..5] ghci> tail [1..5] [1,2,3,4] [2,3,4,5] ghci> null [] ghci> null [[]] True False ghci> take 3 [1..5] ghci> take 100 [1..5] [1,2,3] [1,2,3,4,5] ghci> drop 3 [1..5] ghci> drop 100 [1..5] [4,5] []
Basics: Lists Examples (List operations) ghci> maximum [1,11,22] 22 ghci> minimum [1,11,22] 1 ghci> sum [1..10] 55 ghci> product [10,9..1] 3628800 ghci> a elem "hello" False
Basics: Lists Examples (Ranges) ghci> [ a.. z ] "abcdefghijklmnopqrstuvwxyz" ghci> [7,14..7*10] [7,14,21,28,35,42,49,56,63,70] ghci> [70,63..7] [70,63,56,49,42,35,28,21,14,7] ghci> [0.5,0.7..1.0] [0.5,0.7,0.8999999999999999,1.0999999999999999]
Basics: Lists Examples (List comprehensions) ghci> [x * 2 x <- [50..100], x mod 7 == 0] [112,126,140,154,168,182,196] pairs :: [a] -> [b] -> [(a,b)] pairs xs ys = [(x,y) x <- xs, y <- ys] perms :: (Eq a) => [a] -> [[a]] perms [] = [[]] perms xs = [x:ps x <- xs, ps <- perms (xs \\ [x])]
Basics: Tuples Examples ghci> :t (True,"True", t ) (True,"True", t ) :: (Bool, [Char], Char) ghci> fst (1,2) 1 ghci> snd (1,2) 2 ghci> :t zip zip :: [a] -> [b] -> [(a, b)] ghci> zip [1..] [ a.. d ] [(1, a ),(2, b ),(3, c ),(4, d )]
Example (linecount) $ cat lc.hs main :: IO () main = interact linecount where linecount :: String -> String linecount input = show (length (lines input)) ++ "\n" $ runhaskell lc.hs < lc.hs 6 $ runhaskell lc.hs < hello-world.hs 2
Basics: Algebraic types Algebraic data type definitions are introduced by the keyword data, followed by the name of the type, an equals sign and then the constructors of the type being defined. The simplest sort of algebraic type is defined by enumerating the elements of the type. Examples 1. data Temp = Cold Hot 2. data Season = Spring Summer... 3. data Bool = True False
Basics: Algebraic types Examples 1. type Name = String type Age = Int data Person = Person Name Age 2. data Shape = Circle Float Rectangle Float Float deriving (Eq,Ord,Show,Read)
Basics: Pattern matching Pattern matching is used to specify patterns to which some data should conform and to deconstruct the data according to those patterns. Example (sayme) sayme :: Int -> String sayme 1 = "One!" sayme 2 = "Two!" sayme 3 = "Three!" sayme 4 = "Four!" sayme 5 = "Five!" sayme x = "Not between 1 and 5"
Basics: Pattern matching Example (length) length returns the length of a finite list. length :: [a] -> Int length [] = 0 length (_:xs) = 1 + length xs ghci> length [] 0 ghci> length [1..5] 5
Basics: Pattern matching Example (Numerical expressions) data Expr = Lit Int Add Expr Expr Sub Expr Expr eval :: Expr -> Int eval (Lit n) = n eval (Add e1 e2) = eval e1 + eval e2 eval (Sub e1 e2) = eval e1 - eval e2) Homework: Define a function multexpr :: Expr -> Expr -> Expr that multiplies two numerical expressions.
Basics: Guards Patterns are used to check if the values passed to a function are constructed in a certain way. Guards are used to check if some property of those passed values is true or false. Example (sayme) sayme :: Int -> String sayme n n == 1 = "One!" n == 2 = "Two!" n == 3 = "Three!" n == 4 = "Four!" otherwise = "Not between 1 and 5"
Basics: Lazy evaluation Haskell will compute only what it really must. Examples (Infinite lists) 1. ones :: [Int] ones = 1 : ones 2. powers :: Int -> [Int] powers n = [n^x x <- [0..]] 3. pythagtriples :: [(Int,Int,Int)] pythagtriples = [(x,y,z) z <- [2..], y <- [2..z - 1], x <- [2..y - 1], x*x + y*y == z*z]
Basics: Lazy evaluation Example (The sieve of Eratosthenes) primes :: [Integer] primes = sieve [2..] sieve :: [Integer] -> [Integer] sieve (x:xs) = x : sieve [y y <- xs, y mod x > 0] memberord :: (Ord a) => [a] -> a -> Bool memberord (x:xs) n x < n = memberord xs n x == n = True otherwise = False
Advanced basics: Polymorphism A value is polymorphic if, depending on the context where it is used, it can take more than one type. Example (last) ghci> :type last last :: [a] -> a ghci> last [1,9,8,9] 9 ghci> last "Ummagumma" a Parametric polymorphism is when a function s type signature allows various arguments to take on arbitrary types, but the types must be related to each other in some way.
Advanced basics: Polymorphism Ad hoc polymorphism (or overloading) is when the possible types are limited and must be individually specified before use. Example (show) ghci> :type show show :: Show a => a -> String ghci> show 22 "22" ghci> show 2.2 "2.2" In Haskell, ad hoc polymorphism is achieved by type classes.
Advanced basics: Recursion Recursion is a way of defining functions in which a function calls itself. Example (reverse) reverse returns the elements of a list in reverse order. reverse :: [a] -> [a] reverse [] = [] reverse (x:xs) = reverse xs ++ [x] ghci> reverse [1,2,3,4,5] [5,4,3,2,1] ghci> reverse "man o nam" "man o nam"
Advanced basics: Recursion Example (repeat) repeat takes an element and returns an infinite list composed of that element. repeat :: a -> [a] repeat x = x : repeat x ghci> let ones = repeat 1 ghci> take 5 ones [1,1,1,1,1] ghci> replicate 5 1 [1,1,1,1,1]
Advanced basics: Recursion Example (zip) zip takes two lists and zips them together. zip :: [a] -> [b] -> [(a,b)] zip (x:xs) (y:ys) = (x,y) : zip xs ys zip = [] ghci> zip [1,2,3] ["one","two"] [(1,"one"),(2,"two")]
Advanced basics: Recursion Example (quicksort) quicksort :: (Ord a) => [a] -> [a] quicksort [] = [] quicksort (x:xs) = let left = [a a <- xs, a <= x] right = [a a <- xs, a > x] in quicksort left ++ [x] ++ quicksort right ghci> quicksort ("the quick brown fox " ++ "jumps over the lazy dog") " abcdeeefghhijklmnoooopqrrsttuuvwxyz"
Advanced basics: Higher-order functions Haskell functions can take functions as parameters and return functions as return values. Curried functions and partial application In Haskell, all functions take only one argument. ghci> max 4 5 ghci> (max 4) 5 5 5 ghci> let max4 = max 4 ghci> max4 5 5 max :: (Ord a) => a -> a -> a can also be written as max :: (Ord a) => a -> (a -> a)
Advanced basics: Higher-order functions Example (zipwith) zipwith generalizes zip by zipping with the function given as the first argument. zipwith :: (a b c) [a] [b] [c] zipwith f (x:xs) (y:ys) = f x y : zipwith f xs ys zipwith _ = [] ghci> zipwith (+) [1,2,3,4,5] [1,2,3,2,1] [2,4,6,6,6] ghci> zipwith (*) (replicate 5 2) [1..] [2,4,6,8,10]
Advanced basics: Higher-order functions Example (flip) flip takes a function and returns a function like the original, but with the first two arguments flipped. flip :: (a -> b -> c) -> b -> a -> c flip f y x = f x y ghci> zip [1..5] "aeiou" [(1, a ),(2, e ),(3, i ),(4, o ),(5, u )] ghci> flip zip [1..5] "aeiou" [( a,1),( e,2),( i,3),( o,4),( u,5)]
Advanced basics: Higher-order functions Example (map) map f xs is the list obtained by applying f to each element of xs. map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs ghci> map (+ 2) [1,2,3,2,1] [3,4,5,4,3] ghci> map even [1..5] [False,True,False,True,False]
Advanced basics: Higher-order functions Example (filter) filter takes a predicate and a list, and returns the list of elements that satisfy the predicate. filter :: (a -> Bool) -> [a] -> [a] filter _ [] = [] filter p (x:xs) p x = x : filter p xs otherwise = filter p xs ghci> filter (> 2) [1,2,3,2,1] [3] ghci> filter even [1..5] [2,4]
Advanced basics: Higher-order functions Example (quicksort) quicksort :: (Ord a) => [a] -> [a] quicksort [] = [] quicksort (x:xs) = quicksort left ++ [x] ++ quicksort right where left = filter (<= x) xs right = filter (> x) xs
Advanced basics: Higher-order functions Lambdas Lambdas are anonymous functions that are used when a function is needed only once. ghci> map (\x -> x + 2) [1,2,3,2,1] [3,4,5,4,3] Example (flip) flip :: (a -> b -> c) -> b -> a -> c flip f = \x y -> f y x ghci> zip [1..5] "aeiou" [(1, a ),(2, e ),(3, i ),(4, o ),(5, u )] ghci> flip zip [1,2,3,4,5] "aeiou" [( a,1),( e,2),( i,3),( o,4),( u,5)]
Advanced basics: Higher-order functions Examples (Application operator) ($) :: (a -> b) -> a -> b f $ x = f x ghci> sum $ filter (> 10) $ map (* 2) [2..10] 80 ghci> map ($ 3) [(4 +),(10 *),(^ 2),sqrt] [7.0,30.0,9.0,1.7320508075688772] Examples (Function composition) (.) :: (b -> c) -> (a -> b) -> a -> c f. g = \x -> f (g x) ghci> map (negate. abs) [1,2,-3,-5,4] [-1,-2,-3,-5,-4]
Haskell 101: How to program it 1. Understanding the problem. 2. Designing the program. 3. Writing the program. 4. Looking back. Simon Thompson. Where do I begin? A problem solving approach in teaching functional programming. 1997. www.cs.kent.ac.uk/pubs/1997/208
How to program it Example (The maximum of three integers) 1. Understanding the problem. maxthree :: Int -> Int -> Int -> Int 2. Designing and writing the program. maxtwo :: Int -> Int -> Int maxtwo a b a <= b = b otherwise = a maxthree a b c b <= a && c <= a = a a <= b && c <= b = b otherwise = c maxthree a b c = maxtwo (maxtwo a b) c 3. Looking back.
Haskell 101: Contents Introduction Tutorial Homework Bibliography
Haskell 101: Homework Learn you a Haskell for great good!
Haskell 101: Homework Learn you a Haskell for great good! 1. Download Haskell. 2. Read chapters 1-6 of the tutorial Learn you a Haskell for great good! 3. Answer the following questions: What do you like/dislike about functional programming? What do you like/dislike about Haskell? What do you think of the tutorial?...
Haskell 101: Contents Introduction Tutorial Homework Bibliography
Haskell 101: Bibliography Miran Lipovača. Learn you a Haskell for great good! No Starch Press, 2011. learnyouahaskell.com Bryan O Sullivan, John Goerzen, and Don Stewart. Real world Haskell. O Reilly, 2008. book.realworldhaskell.org
...
Haskell 101: Links PDF: goo.gl/y9ngu Repository: github.com/jpvillaisaza/haskell-101