# Introduction to Weird Functional Languages with Haskell

Alex “saterus” Burkhart The Ohio State University Open Source Club

2011-05-19

Introduction to Weird Functional Languages with Haskell Table of Contents Functional Programming The Functional Paradigm Haskell Basic Syntax Typeclasses Pattern Matching Think Functionally Recursion with Lists Functions as Arguments Higher Order Functions Lambdas Currying Flip Function Composition Laziness

Custom Data Structures List Binary Tree Common Patterns Functors Applicative Functors Monoids Future Topics Where to go to Learn More

Functional Programming

Functional Programming

Functional Programming – The Functional Paradigm

Declarative First Class Functions Pure Functions Immutibility Parallelism

Functional Programming – The Functional Paradigm

Declarative “What” instead of “How” Smart Compilers Safety and Correctness

Functional Programming – The Functional Paradigm

First Class Functions Functions as Data Structures Use Functions as Arguments to Other Functions Abstract Common Patterns

Functional Programming – The Functional Paradigm

Pure Functions No I/O or Modiﬁcation of State Consistent, Predictible Results Safety Optimization

Functional Programming – The Functional Paradigm

Immutability Can’t Change Data Immutable Structures can be Shared Reusing List Links

Functional Programming – The Functional Paradigm

Parallelism Locks Unnecessary Order of Execution negotiated by Compiler

Functional Programming – The Functional Paradigm

Extra Stuﬀ Code Generation with Lisp Type Safety with Haskell and OCaml Massive Paralellism with Erlang Haskell, Erlang, OCaml are all fast

Haskell – Basic Syntax Basic Data Structures Bool, Char, Numbers, List, String, Tuples, Functions True and False ’a’ through ’z’ and more Ratios and Arbitrary Size Numbers [1, 2, 3] (1, 3) (+), sum

Function Signatures 12 :: Int [1, 2, 3] :: [Integer] [’f’, ’o’, ’o’] :: String (1, 3) :: (Int, Int) (+) :: Int -> Int -> Int sum :: [Integer] -> Integer

Algebraic Data Types data Bool = True | False data Int = -2147483648 | -2147483647 | ... | -1 | 0 | 1 | 2 | ... | 2147483647 data Color = Red | Green | Blue data TraﬃcLight = Light String String Color data Maybe a = Nothing | Just a data Either a b = Left a | Right b

Function Deﬁnitions even :: Integer -> Integer -> Bool even x = (mod x 2) == 0 odd :: Integer -> Integer -> Bool odd x = not (even x) doubleMe x = x + x

The Problem Function Scope Equality for the Color type (==) :: Color -> Color -> Bool (==) colorA colorB = ...

Haskell – Typeclasses The Solution Ad-hoc polymorphic interfaces class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool instance Eq Color where (==) :: Color -> Color -> Bool (==) a b = ... (/=) :: Color -> Color -> Bool (/=) a b = not (a == b)

The Win Typeclass Deriving data Color = Red | Green | Blue deriving (Eq, Show, Read) Automatically derive instances of Read, Show, Bounded, Enum, Eq, and Ord.

Function Signatures Updated 12 :: (Num a) => a [1,2,3] :: (Num a) => [a] even :: Integral a => a -> a -> Bool sort :: (Ord a) => [a] -> [a]

Avoid lot’s of manual == comparisons data Color = Red | Green | Blue Implement Show Implement (==)

data Color = Red | Green | Blue show :: Color -> String show Red = “Red” show Green = “Green” show Blue = “Blue”

data Color = Red | Green | Blue (==) :: Color -> Color -> Bool (==) Red Red = True (==) Green Green = True (==) Blue Blue = True (==) _ _ = False

data Maybe a = Nothing | Just a val1 = Just 73 val2 = Nothing possiblyDouble :: Maybe Int -> Maybe Int possiblyDouble x = undeﬁned

data Maybe a = Nothing | Just a val1 = Just 73 val2 = Nothing possiblyDouble :: Maybe Int -> Maybe Int possiblyDouble Nothing = Nothing possiblyDouble (Just x) = x + x

Matching inside Lists myList = [1,2,3,4,5] sum :: [Int] -> Int -> Int sum [] acc = acc sum [x:xs] acc = sum xs (acc + x)

Matching with Case Statements val1 = Just 73 val2 = Nothing possiblyDouble :: Maybe Int -> Maybe Int possibleDouble x = case x of Nothing -> Nothing (Just x) -> x + x

Guards val1 = 5 val2 = 9001 doubleSmall :: Int -> Int doubleSmall x | x <= 9000 = x + x | otherwise = x

Think Functionally

Think Functionally

Think Functionally – Recursion with Lists

myList = [1,2,3,4,5] sum :: [Int] -> Int -> Int sum [] acc = acc sum [x:xs] acc = sum xs (acc + x)

Think Functionally – Functions as Arguments

myList = [1,2,3,4,5] double :: Int -> Int map :: (a -> b) -> [a] -> [b]

Think Functionally – Functions as Arguments

example = “things” toUpper :: Char -> Char map :: (a -> b) -> [a] -> [b]

Think Functionally – Functions as Arguments

myList = [1,2,3,4,5] foldl :: (a -> b -> a) -> a -> [b] -> a sum = ?

Think Functionally – Higher Order Functions

map :: (a -> b) -> [a] -> [b] ﬁlter :: (a -> Bool) -> [a] -> [a] zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] foldl :: (a -> b -> a) -> a -> [b] -> a foldl1 :: (a -> a -> a) -> [a] -> a foldr :: (a -> b -> b) -> b -> [a] -> b foldr1 :: (a -> a -> a) -> [a] -> a any :: (a -> Bool) -> [a] -> Bool all :: (a -> Bool) -> [a] -> Bool

Think Functionally – Lambdas

myList = [1,2,3,4,5] triple = map (\x -> x + x + x) myList divisThree = ﬁlter (\x -> (mod x 3) == 0) myList

Think Functionally – Currying

ghci> :t (+) (+) :: Num a => a -> a -> a ghci> :t (+ 1) (+ 1) :: Num a => a -> a applyTwice :: (a -> a) -> a -> a applyTwice f x = f (f x)

Think Functionally – Flip

ﬂip :: (a -> b -> c) -> b -> a -> c ﬂip f x y = f y x

Think Functionally – Flip

myDiv myDiv myDiv => ? myDiv => ?

:: Fractional a => a -> a -> a xy=x/y 3 12 36 12

Think Functionally – Flip

ﬂip :: (a -> b -> c) -> b -> a -> c myDiv :: Fractional a => a -> a -> a ghci> :t ﬂip myDiv => ? ﬂip myDiv 3 12 => ? ﬂip myDiv 36 12 => ?

Think Functionally – Function Composition

(f ◦ g)(x ) ≡ f (g(x )) – math, not Haskell (.) :: (b -> c) -> (a -> b) -> a -> c f . g = \x -> f (g x) map (\x -> negate (abs x)) [5,-3,-6,7,-3,2,-19] => [-5,-3,-6,-7,-3,-2,-19] map (negate . abs) [5,-3,-6,7,-3,2,-19] => [-5,-3,-6,-7,-3,-2,-19]

Think Functionally – Laziness

Delayed Computation Until Necessary Programs are Transformations of Data Inﬁnite Data Structures Interesting Compiler Optimizations “undeﬁned” Circular Structures Unique to Haskell

Think Functionally – Laziness

Inﬁnite Data Structures Haskell Ranges 1.. :: (Num t) => [t] take 5 [1..] length [1..] – Bad Idea fac 0 = 1 fac n = n * fac (n - 1) ﬁb = 0 : 1 : zipWith (+) ﬁb (tail ﬁb)

Think Functionally – Laziness

Short cut Fusion map f (map g someList) => map (f . g) someList

Think Functionally – Laziness

undeﬁned Valid as long as unevaluated Stub out function signatures

Think Functionally – Laziness Circular Structures No mutable references data Foo = Bar a Foo circularFoo :: Foo Int circularFoo = x where x = Bar 1 y y = Bar 2 x Sci-Fi-Explanation: “You can borrow things from the future as long as you don’t try to change them”

Custom Data Structures

Custom Data Structures

Custom Data Structures – List

data List a = Nil | Cons a (List a) head :: List a -> Maybe a head Nil = Nothing head (Cons x _) = Just x map :: (a -> b) -> List a -> List b map _ Nil = Nil map f (Cons x xs) = Cons (f x) (map f xs)

Custom Data Structures – Binary Tree

data Tree a = Leaf a | Node (Tree a) (Tree a) testTree = Node (Node (Leaf 2) (Node (Node (Leaf 12) (Leaf 7)) (Leaf 3))) (Leaf 9) tMap :: (a -> b) -> Tree a -> Tree b tMap f (Leaf x) = Leaf (f x) tMap f (Node l r) = Node (tMap f l) (tMap f r)

Custom Data Structures – Binary Tree

tFilter :: (a -> Bool) -> Tree a -> [a] tFilter f (Leaf x) | f x = [x] | otherwise = [] tFilter f (Node l r) = (tFilter f l) ++ (tFilter f l)

Custom Data Structures – Binary Tree

tFoldDf :: (a -> b -> a) -> a -> Tree b -> a tFoldDf f acc (Leaf x) = f acc x tFoldDf f acc (Node l r) = tFoldDf f (tFoldDf f acc l) r treeMax t = tFoldDf max 0 t treeMin t = tFoldDf min 0 t

Custom Data Structures – Binary Tree

member :: (Eq a) => Tree a -> a -> Maybe a member t e = tFoldDf member’ Nothing t where member’ acc x | x == e = Just x | otherwise = acc

Common Patterns

Common Patterns

Common Patterns – Functors

map :: (a -> b) -> [a] -> [b] lmap :: (a -> b) -> List a -> List b tMap :: (a -> b) -> Tree a -> Tree b

Common Patterns – Functors

class Functor a where fmap :: Functor f => (a -> b) -> f a -> f b instance Functor [a] where fmap :: (a -> b) -> [a] -> [b] fmap = map instance Functor (Tree a) where fmap :: (a -> b) -> Tree a -> Tree b fmap = tMap

Common Patterns – Functors

class Functor a where fmap :: Functor f => (a -> b) -> f a -> f b instance Functor Maybe where fmap :: (a -> b) -> Maybe a -> Maybe b fmap _ Nothing = Nothing fmap f Just x = Just (f x) possiblyDouble m = fmap double m where double x = x + x

Common Patterns – Functors

Recall Currying... plusX m = fmap plux m where plux x = (+ x) uh oh... ghci> :t plusX [1,2,3,4,5] plusX [1,2,3,4,5] :: Num a => [a -> a]

Common Patterns – Applicative Functors

ghci> :t plusX [1,2,3,4,5] plusX [1,2,3,4,5] :: Num a => [a -> a] fmap again? class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b plusX [1,2,3,4] <*> [10]

Common Patterns – Applicative Functors

instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just f) <*> something = fmap f something pure (+3) <*> Just 9 Just (++"hahah") <*> Nothing Nothing <*> Just "woot" pure (+) <*> Just 3 <*> Just 5

Common Patterns – Monoids

Monoids class Monoid a where mempty :: Monoid a => a mappend :: Monoid a => a -> a -> a mconcat :: Monoid a => [a] -> a instance Monoid [a] where mempty = [] mappend = (++) mconcat = foldr mappend mempty

Common Patterns – Monoids

instance (Monoid a) => Monoid (Maybe a) where mempty = Nothing mappend Nothing x = x mappend x Nothing = x mappend (Just x) (Just y) = Just (x `mappend` y)

Trees as Maps Zippers Finger Trees (will blow your mind)

Common Patterns – Future Topics Testing/Quickcheck Error Handling Mutable Objects and Arrays Parallel Programming and STM Functional Reactive Programming Foreign Function Interface Cabal and Hackage Examine Real Code
XMonad Window Manager (<1000 lines) Parsec Yesod Web Framework Darcs, Version Control System The Glorious Glasgow Haskell Compiler

Agda Theorem Prover

3 2

1

Write Yourself a Scheme in 48 Hours

4

Hackage Package Repository Hoogle API Search Hayoo API Search
2 3 4

1