Download - Why Haskell Matters

Transcript
Page 1: Why Haskell Matters

Why Haskell Matters

Roman Gonzalez

Vancouver Haskell Meetup

October 20, 2010

Page 2: Why Haskell Matters

So what is this language about?

Haskell is a pure, statically typed, lazy functionalprogramming language.

→ Name inspired by mathematician Haskell Brooks Curry

→ Based on a more primitive language called Lambda Calculus

→ There is no iteration or sequences of actions, everything isrecursive

Page 3: Why Haskell Matters

When learning Haskell is a good idea?

→ If you are a experienced developer that wants to growprofessionally by learning completely new and differentapproaches to solve problems

→ If you need to build systems where correctness is critical(Banks, Safety-Critical Systems)

→ Is well suited to implement Domain Specific Languages, so itcould work very well in systems programming

→ as Erlang, it is easy to implement parallel and concurrentprograms safely due to the pureness of the language

Page 4: Why Haskell Matters

Benefits of using Haskell

→ Algorithms are normally shorter and more concise than theiriterative versions

→ Due to the use of function composability, curryfication andhigh-order functions, code can be reused in really smart ways

→ The kick-ass type system with type inference makes youdevelop code that would normally work at the first compilation

Page 5: Why Haskell Matters

Properties of Haskell

→ Functions won’t perform sequentially, instead they willevaluate expressions when needed (lazily)

→ There is a controlled environment for side effect functions butby default functions are pure (non-side effect).

→ Management of resources is abstracted completely from thedeveloper (GC and automatic allocation of data included)

→ Strong typing makes correctness happen, and most of the theissues regarding this type systems won’t get on the way due tothe compiler’s type inference system

Page 6: Why Haskell Matters

Quicksort in C

void qsort(int a[], int lo, int hi) {

int h, l, p, t;

if (lo < hi) {

l = lo;

h = hi;

p = a[hi];

do {

while ((l < h) && (a[l] <= p))

l = l+1;

while ((h > l) && (a[h] >= p))

h = h-1;

if (l < h) {

t = a[l];

a[l] = a[h];

a[h] = t;

}

} while (l < h);

a[hi] = a[l];

a[l] = p;

qsort( a, lo, l-1 );

qsort( a, l+1, hi );

}

}

Page 7: Why Haskell Matters

Quicksort in Haskell

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

qsort [] = []

qsort (x:xs) = (qsort lower) ++ [x] ++ (qsort upper)

where

lower = filter (< x) xs

upper = filter (>= x) xs

-- qsort [4,5,1,6,3,2]

-- First execution:

-- x = 4

-- xs = [5,1,6,3,2]

-- lower = [1,3,2]

-- upper = [5,6]

Page 8: Why Haskell Matters

Simple FunctionsOne parameter functions

Haskell has only one parameter functions

inc :: Int -> Int

inc x = x + 1

isNotZero :: Int -> Bool

isNotZero x = x /= 0

Page 9: Why Haskell Matters

High Order FunctionsFunctions that returns functions

add :: Int -> (Int -> Int)

add x = \y -> x + y

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

compare a = \b -> a == b

-- Syntactic Sugar complements of Haskell

add’ :: Int -> Int -> Int

add’ x y = x + y

compare’ :: (Eq a) => a -> a -> Bool

compare’ x y = x == y

Page 10: Why Haskell Matters

High Order FunctionsAssign returned functions directly

If inc is a function of type:

Int -> Int

and (+1) is a function of type:

Int -> Int

Then why don’t assign it directly? This is called curryfication

inc’ = (1 +)

isNotZero’ = (0 /=)

Page 11: Why Haskell Matters

High Order FunctionsFunctions that receive functions as parameters

Functions can also receive functions as parameters:

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

filter fn (x:xs)

| fn x = x : filter fn xs

| otherwise = filter fn xs

-- filter isNotZero [1,0,2,0,3]

-- => [1,2,3]

They can also be curryfied:

removeZeros :: [Int] -> [Int]

removeZeros = filter isNotZero

Page 12: Why Haskell Matters

ListsDefinition of a list

→ An empty value: []

→ A cons value: Item on the left and list on the right, the wholething being a new list[1,2,3] == (1:2:3:[]) == (1:(2:(3:[])))

So we have two basic functions to get the two components of acons:

head :: [a] -> a

head (x:_) = x

tail :: [a] -> [a]

tail (_:xs) = xs

Page 13: Why Haskell Matters

Let’s define some functionsSimple functions with a common interface

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

sum [] = 0

sum (x:xs) = x + sum xs

prod :: (Num a) => [a] -> a

prod [] = 1

prod (x:xs) = x * prod xs

length :: [a] -> Int

length [] = 0

length (x:xs) = 1 + length xs

Page 14: Why Haskell Matters

FoldingBasics

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

foldr fn zero [] = zero

foldr fn zero (x:xs) = fn x (foldr fn zero xs)

{-

foldr (+) 0 [3,2,5]

- [] is replaced by 0

- (:) function is replaced by the (+) function

-> 3 : (2 : (5 : []))

-> 3 + (2 + (5 + 0))

-}

Page 15: Why Haskell Matters

FoldingUsing foldr and partially applied functions

-- foldr (+) 0 :: (Num a) => [a] -> a

sum’ = foldr (+) 0

-- foldr (*) 1 :: (Num a) => [a] -> a

prod’ = foldr (*) 1

-- foldr (+) 0 :: (Num a) => [a] -> a

length’ = foldr (\_ accum -> 1 + accum) 0

Page 16: Why Haskell Matters

FoldingInsertion Sort

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

insertion a [] = [a]

insertion a (b:bs)

| a <= b = (a:b:bs)

| otherwise = (b : insertion a bs)

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

insertionSort = foldr insertion []

{-

insertionSort [3,2,4]

-> insertion 3 (insertion 2 (insertion 4 ([])))

-}

Page 17: Why Haskell Matters

Function CompositionBasics

Let’s abstract the composition of functions

(.) :: (b -> c) -> (a -> b) -> (a -> c)

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

Using the (.) function, we can compose function together tocreate new ones:

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

map fn = foldr ((:) . fn) []

-- (x:xs) == (:) x xs

-- (:) . fn = \x -> (:) fn x

Page 18: Why Haskell Matters

Lazy EvaluationInfinite Lists

Haskell is a lazy language, meaning that the language will evaluateexpressions only one needed.

iterate :: (a -> a) -> a -> [a]

iterate fn a = (a : iterate fn (fn a))

-- [a, fn a, fn (fn a), fn (fn (fn a))), ...]

This will do an infinite recursion, it will stop when algorithms donot require more values from the infinite lists

bitValues :: [Int]

bitValues = iterate (*2) 1

-- take 8 bitValues -> [1,2,4,8,16,32,64,128]

Page 19: Why Haskell Matters

Algebraic Data TypesMaybe Data Type

To handle nullable values we use an Algebraic Data Type calledMaybe

data Maybe a = Just a

| Nothing

deriving (Show)

Where the a in the Maybe could be any type (Int, String, Char)

Examples of values of type Maybe Int

→ Just 20

→ Nothing

Page 20: Why Haskell Matters

Unfolds

unfoldr :: (a -> Maybe (b, a)) -> a -> [b]

unfoldr fn x =

case fn x of

Just (a, b) -> a : (unfoldr fn b)

Nothing -> []

Page 21: Why Haskell Matters

From Int to [Bit]

type Bit = Int

nextBit :: Int -> Maybe (Bit, Int)

nextBit x

| x > 0 = Just (m, d)

| otherwise = Nothing

where

d = x ‘div‘ 2

m = x ‘mod‘ 2

toBinary :: Int -> [Bit]

toBinary = unfoldr nextBit

Page 22: Why Haskell Matters

Binary to DecimalExample of high-order functions, composability and infinite lists

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

zipWith _ _ [] = []

zipWith _ [] _ = []

zipWith fn (x:xs) (y:ys) = (fn x y) : zipWith fn xs ys

binaryToDecimal :: [Bit] -> Int

binaryToDecimal = sum . zipWith (*) bitValues

Page 23: Why Haskell Matters

Why Haskell is not being used as much?

→ It’s different, people is always afraid of what is different

→ It’s difficult, mostly related to the first point

→ It’s unpopular, mostly related to the first and second point

→ It’s risky (for employers), there are not many Haskelldevelopers to count on, of course this is mostly related to thefirst, second and third point

→ Libraries are broad, but there is no depth (Many incompatibleexperimental libraries that do the same thing)

Page 24: Why Haskell Matters

Thank You!

Get started at learnyouahaskell.comGithub: http://github.com/roman/haskell meetup

Twitter: @romanandreg


Top Related