print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1...

15
Haskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string and adds a newline character. putStr displays a string but does not add the newline character putStrLn “Hello World” -- displays Hello World print “Hello World” -- displays “Hello World” For multiple I/O expressions in one line use a do block do { putStr "2 + 2 = " ; print (2 + 2) } -- displays 2 + 2 = 4 do { putStrLn "ABCDE" ; putStrLn "12345" } -- displays ABCDE 12345 Simple arithmetic: 2 + 15 49 * 100 1892 - 1472 5 / 2 50 * 100 - 4999 50 * (100 - 4999) Surround negative numbers with brackets: 5 * (-3) Boolean algebra uses True, False, not (not), && (and) ||(or) not (True && True) Test for equality with == and inequality with /= infix functions like * stand between the operators Most functions are prefix functions: succ 8 -- displays 9 min 3 4 -- displays 3 max 4 5 -- displays 5 div 13 6 -- displays 2 odd 5 -- displays True Prefix functions can be written as infix with backticks: div 92 10 92 `div` 10

Transcript of print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1...

Page 1: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

1

Comments begin with two dashes --

print, putStr, putStrLn

putStrLn displays a string and adds a newline character. putStr displays a string but does not add the newline character putStrLn “Hello World” -- displays Hello World

print “Hello World” -- displays “Hello World”

For multiple I/O expressions in one line use a do block

do { putStr "2 + 2 = " ; print (2 + 2) } -- displays 2 + 2 = 4

do { putStrLn "ABCDE" ; putStrLn "12345" } -- displays ABCDE

12345

Simple arithmetic:

2 + 15

49 * 100

1892 - 1472

5 / 2

50 * 100 - 4999

50 * (100 - 4999)

Surround negative numbers with brackets:

5 * (-3)

Boolean algebra uses True, False, not (not), && (and) ||(or)

not (True && True)

Test for equality with == and inequality with /= infix functions like * stand between the operators Most functions are prefix functions:

succ 8 -- displays 9

min 3 4 -- displays 3

max 4 5 -- displays 5

div 13 6 -- displays 2

odd 5 -- displays True

Prefix functions can be written as infix with backticks:

div 92 10

92 `div` 10

Page 2: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

2

Functions are defined with = doubleMe x = x + x

doubleUs x y = x*2 + y*2 IF statements have a THEN and always require an ELSE

doubleSmallNumber x = if x > 100

then x

else x*2

IF is an expression in Haskell which means it must evaluate to a result. In imperative languages,

IF is usually a statement. That means that you must have an ELSE. If not and the condition was

false you wouldn’t get a result.

Lists are collections of elements of the same type

lostNumbers = [4,8,15,16,23,42]

someString = "Some string"

Use ++ to concatenate two lists

[1,2,3,4] ++ [6,7,8] -- displays [1,2,3,4,6,7,8]

"Hello" ++ " " ++ "world" – displays "Hello world"

Use : to prepend what is on the left of the colon to the list of the right

'A':" SMALL CAT" -- displays A SMALL CAT

1:[2,3,4,5] -- displays [1,2,3,4,5]

1:2:3:[] -- displays [1,2,3]

Use !! to get an element of a list by its index number (0 based and the index must exist) "Hello World!" !! 6 -- displays “W”

Use <, <=, > and >= to compare lists

List ranges are defined with ‘..’

[1..20]

['a'..'z']

Page 3: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

3

Ranges can define a step size

[2,4..20] --([2,4,6,8,10,12,16,18,20])

[3,6..20] --([3,6,9,12,15,18])

[20,19..15] --([20,19,18,17,16,15])

List related functions

head [5,4,3] -- first element of a list (5)

tail [5,4,3] -- the tail without the head

last [5,4,3] -- the last element of a list

init [5,4,3] -- list without tail ([5,4])

length [5,4,3] -- number of elements (3)

null [5,4,3] -- whether list is empty (False)

reverse [5,4,3] -- reverse list ([3,4,5])

take 3 [5,4,3,2,1] -- extract number of elements from list start

([5,4,3])

drop 3 [5,4,3,2,1] -- drop first elements of a list ([2,1])

maximum [5,4,3,2,1] -- maximum of orderable list (5)

minimum [5,4,3,2,1] -- minimum of orderable list (1)

sum [5,4,3] -- sum of number list (12)

product [5,4,3] -- product of number list (60)

4 `elem` [5,4,3] -- whether element is in list, usually infixed

(True)

take 10 (cycle [1,2,3]) -- repeat the list elements

([1,2,3,1,2,3,1,2,3,1])

take 10 (repeat 5) -- repeat the element ([5,5,5,5,5,5,5,5,5,5])

replicate 3 10 -- repeat the element a number of times ([10,10,10])

Page 4: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

4

List comprehensions are similar to mathematical equations

[x*2 | x <- [1..5]] --([2,4,6,8,10]) Predicates are conditions for list comprehensions

[x*2 | x <- [1..5], x*2 >= 5] --([6,8,10]) There can be more than one predicate

[ x | x <- [10..20], x /= 10, x /= 15, x /= 19] Note: /= is not equal to

Comprehensions can be put inside a function

-- call the function with a list of integers as an argument

-- e.g. boomBangs [2,7,13]. For each odd number in the list, ‘BOOM’

-- will be printed if it’s under 10 and ‘BANG’ if its over 10.

boomBangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd

x]

Comprehensions can draw from several lists, which multiplies the lengths

[ x*y | x <- [2,3], y <- [3,4,5]] ([6,8,10,9,12,15])

An underscore ( _) is a dummy placeholder for an unused value

length' xs = sum [1 | _ <- xs] List comprehensions can be nested

let xxs = [[1,2,3],[2,3,4],[4,5]] [ [x | x <- xs, even x] | xs <- xxs] ([[2],[2,4],[4]]

Tuples can contain several types, but for the type of two Tuples to be the same, the number and types of their elements must match

(1,2)

[(1,2), (3,2), (4,9)]

[("Johnny", "Walker", 38), ("Kate", "Middleton", 27)]

Only show values greater or equal to 5

Page 5: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

5

Tuple related functions

fst (8,11) -- returns first component of a pair (8)

snd (9,"Hey") -- returns second component of a pair ("Hey")

zip[1..3] ['a'..'c'] -- combines two lists to a list of tuples

--( [(1,'a'), (2,'b'), (3,'c')] )

Types and Typeclasses Types always start with an uppercase letter Use :t to get a type of something: :t 'a' -- returns ('a' :: Char)

:t "HELLO" -- returns ("HELLO" :: [Char])

:t (True, 'a') -- returns ( (True,'a') :: (Bool, Char) )

All functions should use a type declaration with :: ("has type of"). Multiple arguments are also separated with -> just like the type declaration itself. removeUppercase :: [Char] -> [Char]

removeUppercase :: String -> String

addThree :: Int -> Int -> Int -> Int

addThree x y z = x + y + z

Common Data Types

• Int : Integer

• Integer : Integer (big)

• Float : Floating point

• Double : Floating point with double precision

• Bool : Boolean

• Char : Character

• Tuples, as mentioned in chapter 2

• Ordering : Can be GT, LT or EQ

Type variables can be used in function declarations. They stand for a type. Without a class constraint they mean "any type"

:t head -- (head :: [a] -> a)

:t fst --(fst :: (a, b) -> a)

Typeclasses are like interfaces for types. If a type is part of a typeclass it implements that class' behaviour. The => symbol separates the class constraint from the declaration:

:t (==) ( (==) :: (Eq a) => a -> a -> Bool )

Page 6: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

6

o Eq --supports equality testing o Ord : can have ordering o Show : can be presented as string o Read : can be read from a string o Enum : ordered type which can be enumerated o Bounded : have an upper and lower bound o Num : can act like a number o Integral : can act like an integral number o Floating : can act like a floating point number o Related functions o 5 `compare` 3 : takes two Ord members of same type and returns a Ordering (GT) o show 3 : takes a Show and returns a String ("3") o read "True" : takes a Read and returns a Read (True) o succ LT : takes a Enum and returns next element (GT) o pred 'b' : takes a Enum and returns previous element ('a') o minBound :: Bool : takes a Bounded and returns lower bound (False) o maxBound :: Bool : takes a Bounded and returns lower bound (True) o fromIntegral 5 : takes a Integral and returns a Num

Type annotations define the type of ambiguous expressions (read "5" :: Float) * 4

Syntax in Functions Functions can be defined with pattern matching. Patterns make sure that the input matches a specified pattern. The first matching pattern is executed. There should always be a catch-all pattern at the end

lucky :: (Integral a) => a -> String

lucky 7 = "LUCKY NUMBER SEVEN!"

lucky x = "Sorry, you're out of luck, pal!"

factorial :: (Integral a) => a -> a

factorial 0 = 1

factorial n = n * factorial (n - 1)

addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a)

addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)

length' :: (Num b) => [a] -> b

length' [] = 0

length' (_:xs) = 1 + length' xs

sum' :: (Num a) => [a] -> a

sum' [] = 0

sum' (x:xs) = x + sum' xs

The as pattern is used to reference the "whole thing": Put a name followed by @ in front of the

Page 7: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

7

pattern: capital :: String -> String

capital "" = "Empty string, whoops!"

capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]

Guards are similar to if statements and check for Boolean conditions. The pipes (vertical lines) after the function’s name show that these are guards.

f x

| predicate1 = expression1

| predicate2 = expression2

| predicate3 = expression3

For example, in the game of golf for a single hole, a player takes a number of strokes. There is a ‘par’ score for the hole, which is the expected number of strokes. holeScore :: Int -> Int -> String

holeScore strokes par

| score < 0 = show (abs score) ++ " under par"

| score == 0 = "level par"

| otherwise = show(score) ++ " over par"

where score = strokes-par

Note: the score variable defined in the where clause is in scope for all three guards Guards can be combined with patterns: If all guards of a function evaluate to False, evaluation falls through to the next pattern Guards can have as many parameters as you like. Another example myCompare :: (Ord a) => a -> a -> Ordering

a `myCompare` b

| a > b = GT

| a == b = EQ

| otherwise = LT

Note: backticks allow you to use infix even when defining functions Let bindings are similar to where bindings. Their form is let <bindings> in <expression>. cylinder :: (RealFloat a) => a -> a -> a

cylinder r h =

let sideArea = 2 * pi * r * h

topArea = pi * r ^2

in sideArea + 2 * topArea

The difference between let bindings and where bindings is that let bindings are expressions, just like if statements:

Page 8: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

8

4 * (if 10 > 5 then 10 else 0) + 2 (42)

4 * (let a = 9 in a + 1) + 2 (42)

Let bindings can be used to introduce functions in a local scope [let square x = x * x in (square 5, square 3, square 2)] (

[(25,9,4)] )

To let bind several variables they get separated by a semicolon (let a = 100; b = 200; c = 300 in a*b*c, let foo="Hey "; bar =

"there!" in foo ++ bar)

Let bindings can be used with pattern matching (let (a,b,c) = (1,2,3) in a+b+c) * 100 (600)

Let bindings can be used in list comprehensions calcBmis :: (RealFloat a) => [(a, a)] -> [a]

calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2]

Predicates come after the let binding calcBmis :: (RealFloat a) => [(a, a)] -> [a]

calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0]

Case expressions are very similar to pattern matching: head' :: [a] -> a

head' [] = error "No head for empty lists!"

head' (x:_) = x

head' :: [a] -> a

head' xs = case xs of [] -> error "No head for empty lists!"

(x:_) -> x

case expression of pattern -> result

pattern -> result

pattern -> result

...

Pattern matching can only be used with function definitions. Cases expressions work everywhere describeList :: [a] -> String

describeList xs = "The list is " ++ case xs of [] -> "empty."

[x] -> "a singleton list."

xs -> "a longer list."

Recursion Try to start with the edge cases maximum' :: (Ord a) => [a] -> a

maximum' [] = error "maximum of empty list"

maximum' [x] = x

Page 9: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

9

maximum' (x:xs)

| x > maxTail = x

| otherwise = maxTail

where maxTail = maximum' xs

maximum' :: (Ord a) => [a] -> a

maximum' [] = error "maximum of empty list"

maximum' [x] = x

maximum' (x:xs) = max x (maximum' xs)

replicate' :: (Num i, Ord i) => i -> a -> [a]

replicate' n x

| n <= 0 = []

| otherwhise = x:replicate' (n-1) x

take' :: (Num i, Ord i) => i -> [a] -> [a]

take' n _

| n <= 0 = []

take' _ [] = []

take' n (x:xs) = x : take' (n-1) xs

reverse' :: [a] -> [a]

reverse' [] = []

reverse' (x:xs) = reverse' xs ++ [x]

repeat' :: a -> [a]

repeat' x = x:repeat' x

zip' :: [a] -> [b] -> [(a,b)]

zip' _ [] = []

zip' [] _ = []

zip' (x:xs) (y:ys) = (x,y):zip' xs ys

elem' :: (Eq a) => a -> [a] -> Bool

elem' a [] = False

elem' a (x:xs)

| a == x = True

| otherwise = a `elem'` xs

Quicksort can be implemented very elegantly. The main algorithm is A sorted list is a list that has all the values smaller than (or equal to) the head of the list in front (and those values are sorted), then comes the head of the list in the middle and then come all the values that are bigger than the head (they're also sorted) quicksort :: (Ord a) => [a] -> [a]

quicksort [] = []

quicksort (x:xs) =

let smallerSorted = quicksort [a | a <- xs, a <= x]

biggerSorted = quicksort [a | a <- xs, a > x]

in smallerSorted ++ [x] ++ biggerSorted

Higher order functions Higher order functions take other functions as parameters and return functions themselves (which is what makes up the ultimate Haskell experience) Functions in Haskell only take one argument Curried functions are used to give the impression that a function can have more than one argument: Calling max 4 5 creates a function which takes one argument and returns 4 if the argument is smaller and the argument itself if it is bigger than 4. These calls are equivalent:

Page 10: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

10

max 4 5

(max 4) 5

A space between two things is simply function application. The type of max can be written in two equivalent ways: max :: (Ord a) => a -> a -> a

max :: (Ord a) => a -> (a -> a)

It takes an a and returns a function, which takes another a and returns an a. If a function is called with not all parameters we get back a partially applied function. multThree :: (Num a) => a -> a -> a -> a

multThree x y z = x * y * z

When we do multThree 3 5 9 it's actually ((multThree 3) 5) 9

-- or

multThree :: (Num a) => a -> (a -> (a -> a))

First multThree 3 is applied, which returns a function. This function takes a single argument and returns another function. This other function again takes a single argument and returns the parameter multiplied by 15. This allows us to do things like: multTwoWithNine = multThree 9

multTwoWithNine 2 3 (54)

multWithEighteen = multTwoWithNine 2

multWithEighteen 10 (180)

A function that compares the argument with 100 could be written like: compareWithHundred :: (Num a, Ord a) => a -> Ordering

compareWithHundred x = compare 100 x

The part compare 100 returns a function that takes a number and compares it with 100. The above thus can be rewritten as: compareWithHundred :: (Num a, Ord a) => a -> Ordering

compareWithHundred = compare 100

More examples divideByTen :: (Floating a) => a -> a

divideByTen = (/10)

isUpperAlphanum :: Char -> Bool

isUpperAlphanum = (`elem` ['A'..'Z'])

Page 11: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

11

The type declaration of functions that take functions look different applyTwice :: (a -> a) -> a -> a

applyTwice f x = f (f x)

applyTwice (+3) 10 (13)

applyTwice (++ " HAHA") "HEY" ("HEY HAHA HAHA")

applyTwice ("HAHA " ++) "HEY" ("HAHA HAHA HEY")

applyTwice (multThree 2 2) 9 (144)

applyTwice (3:) [1] ([3,3,1])

zipWith takes a function and two lists and applies the function on each two items of both lists to get a new list zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]

zipWith' _ [] _ = []

zipWith' _ _ [] = []

zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys

zipWith' (+) [4,2,5,6] [2,6,2,3] ([6,8,7,9])

zipWith' max [6,3,2,1] [7,3,1,5] ([7,3,2,5])

zipWith' (++) ["foo ", "bar "] ["fighters", "hoppers"] (["foo

fighters", "bar hoppers"])

zipWith' (*) (replicate 5 2) [1..] ([2,4,6,8,10])

zipWith' (zipWith'(*)) [ [1,2], [3,4] ] [ [2,3], [4,5] ]

([[2,6],[12,20]])

flip takes a function and returns a function where the first two parameters are flipped flip' :: (a -> b -> c) -> (b -> a -> c)

flip' f = g

where g x y = f y x

Or even shorter

flip' :: (a -> b -> c) -> b -> a -> c

flip' f y x = f x y

zipWith (flip' div) [2,2..] [10,8,6,4,2] ( [5,4,3,2,1] )

The map function takes a function and a list and returns a list with the function applied to every element

map :: (a -> b) -> [a] -> [b]

map _ [] = []

map f (x:xs) = f x : map f xs

map (+3) [1,5,3,1,6] --([4,8,6,4,9])

map (++ "!") ["BIFF", "BANG"] --(["BIFF!","BANG!"])

map (replicate 2) [3..6] --([[3,3],[4,4],[5,5],[6,6]])

map (map (^2)) [[1,2],[3,4,5]] --([[1,4],[9,16,25]])

map fst [(1,2),(3,5)] --([1,3])

Page 12: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

12

The filter function takes a function that filters elements from a list

filter :: (a -> bool) -> [a] -> [a]

filter _ [] = []

filter p (x:xs)

| p x = x : filter p xs

| otherwise = filter p xs

filter (>3) [1,5,3,6] --([5,6])

filter even [1..10] --([1,2,4,6,8,10])

let notNull x = not (null x) in filter notNull [[1,2,3],[],[2,2]]

([[1,2,3],[2,2]])

Alternative quicksort implementation

quicksort :: (Ord a) => [a] -> [a]

quicksort [] = []

quicksort (x:xs) =

let smallerSorted = quicksort (filter (<=x) xs)

biggerSorted = quicksort (filter (>x) xs)

in smallerSorted ++ [x] ++ biggerSorted

The takeWhile function takes a predicate function and a list. It returns elements from the list until the predicate becomes False. Sum of all odd squares that are smaller than 10000 sum (takeWhile (<10000) (filter odd (map (^2) [1..])))

Alternative with list comprehension sum (takeWhile (<10000) [n^2 | n <- [1..], odd (n^2)])

Example: The Collatz sequence starts at any number. If the number is even, it's divided by 2. If it is odd it is multiplied by 3 and 1 is added. In any case the chain continues at this new number until the sequence reaches 1. Question: For all starting numbers between 1 and 100, how many chains have a length greater than 15? chain :: (Integral a) => a -> [a]

chain 1 = [1]

chain n

| even n = n:chain (n `div` 2)

| odd n = n:chain (n*3 + 1)

numLongChains :: Int

Page 13: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

13

numLongChains = length (filter isLong (map chain [1..100]))

where isLong xs = length xs > 15

Lambdas are anonymous functions. They are defined with a \, followed by space separated parameters, and a -> that points at the function body: numLongChains :: Int

numLongChains = length (filter (\xs -> length xs > 15) (map chain

[1..100]))

zipWith (\a b -> (a * 30 + 3) / b) [5,4,3,2,1] [1,2,3,4,5]

map (\(a,b) -> a + b) [(1,2),(3,5),(6,3),(2,6),(2,5)]

flip' f = \x y -> f y x

Sometimes lambdas are used even if that is not neccessary, like map (\x -> x + 3) [1,6,3,2] instead of more readable map (+3) [1,6,3,2]. Folds take a binary function a start value and a list as parameter. The binary function is called with the accumulator and the first (or last) element from the list and produces a new accumulator. Then it's called again with this new accumulator and the next list element. Whenever you want to traverse a list to return something, chances are you want a fold. foldl or left fold folds up a list from the left side. sum' :: (Num a) => [a] -> a

sum' xs = foldl (\acc x -> acc + x) 0 xs

In the beginning the binary function is called with acc value 0 and the first list element. The lambda function (\acc x -> acc + x) is the same as (+) and we can omit xs because foo a = bar b a can be written as foo = bar b: sum' :: (Num a) => [a] -> a

sum' = foldl (+) 0

elem' :: (Eq a) => a -> [a] -> Bool

elem' y ys = foldl (\acc x -> if x == y then True else acc) False ys

foldr does a right fold. Here the parameters to the binary function are flipped. map' :: (a -> b) -> [a] -> [b]

map' f xs = foldr (\x acc -> f x : acc) [] xs

We could also use foldl with the function \acc x -> acc ++ [f x]. But ++ is much more expensive than :. Right folds are usually used to build up lists. Right folds also work with infinite lists whereas left folds don't. foldl1 and foldr1 work like foldl and foldr but use the first (or last) list element as starting value. They don't work with empty lists.

Page 14: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

14

sum = foldl1 (+)

Fold examples maximum' :: (Ord a) => [a] -> a

maximum' = foldr1 (\x acc -> if x > acc then x else acc)

reverse' :: [a] -> [a]

reverse' = foldl (\acc x -> x : acc) []

-- alternative

reverse' = foldl (flip (:)) []

product' :: (Num a) => [a] -> a

product' = foldr1 (*)

filter' :: (a -> Bool) -> [a] -> [a]

filter' p = foldr (\x acc -> if p x then x : acc else acc) []

head' :: [a] -> a

head' = foldr1 (\x _ -> x)

last' :: [a] -> a

last' = foldl1 (\_ x -> x)

scanl and scanr are like foldl and foldr but they also give all intermediate results back scanl (+) 0 [3,5,2,1] ([0,3,8,10,11])

scanr (+) 0 [3,5,2,1] ([11,8,3,1,0])

scanl1 (\acc x -> if x > acc then x else acc) [3,2,9,2,1]

([3,3,9,9,9])

scanl (flip (:)) [] [3,2,1] ([[],[3],[2,3],[1,2,3]])

How many elements does it take for the sum of the roots of all natural numbers to exceed 1000? sqrtSums :: Int

sqrtSums = length (takeWhile (<1000) (scanl1 (+) (map sqrt [1..])))

+ 1

The function application function $ looks like ($) :: (a -> b) -> a -> b

f $ x = f x

It has lowest precedence and thus can often be used instead of parentheses: sum $ map sqrt [1..130] instead of sum (map sqrt [1..130]) or sum $ filter (> 10) $ map (*2) [2..10] instead of sum (filter (> 10) (map (*2) [2..10])).

Page 15: print, putStr, putStrLnlearnco.de/wp-content/uploads/Haskell-Commands_v1.2.pdfHaskell - Commands 1 Comments begin with two dashes -- print, putStr, putStrLn putStrLn displays a string

Haskell - Commands

15

It also allows to map function application to a list of functions like map ($ 3) [(4+), (10*), (^2), sqrt]. Function composition is done with the . function. If called with two functions f and g it returns a new function. This function is like calling f with argument x and then g with that result: f( g(x) ). (.) :: (b -> c) -> (a -> b) -> a -> c

f . g = \x -> f (g x)

map (\x -> negate (abs x)) [5,-3,-6,7,-3,2,-19,24]

map (\xs -> negate (sum (tail xs))) [[1..5],[3..6],[1..7]]

sum (replicate 5 (max 6.7 8.9))

replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5]

[4,5,6,7,8])))

-- same with function composition

map (negate . abs) [5,-3,-6,7,-3,2,-19,24]

map (negate . sum . tail) [[1..5],[3..6],[1..7]]

sum . replicate 5 . max 6.7 $ 8.9

replicate 100 . product . map (*3) . zipWith max [1,2,3,4,5] $

[4,5,6,7,8]

A common use case for function composition is defining function in so called point free style. It's when we write sum' = foldl (+) 0 instead of sum' xs = foldl (+) 0 xs (omitting the xs). fn x = ceiling (negate (tan (cos (max 50 x))))

-- in point free style

fn = ceiling . negate . tan . cos . max 50