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 Modification 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 Stuff Code Generation with Lisp Type Safety with Haskell and OCaml Massive Paralellism with Erlang Haskell, Erlang, OCaml are all fast

Haskell

Haskell

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

Haskell – Basic Syntax

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

Haskell – Basic Syntax

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

Haskell – Basic Syntax

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

Haskell – Typeclasses

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)

Haskell – Typeclasses

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

Haskell – Typeclasses

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

Haskell – Pattern Matching

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

Haskell – Pattern Matching

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

Haskell – Pattern Matching

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

Haskell – Pattern Matching

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

Haskell – Pattern Matching

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

Haskell – Pattern Matching

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

Haskell – Pattern Matching

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

Haskell – Pattern Matching

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] filter :: (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 = filter (\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

flip :: (a -> b -> c) -> b -> a -> c flip 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

flip :: (a -> b -> c) -> b -> a -> c myDiv :: Fractional a => a -> a -> a ghci> :t flip myDiv => ? flip myDiv 3 12 => ? flip 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 Infinite Data Structures Interesting Compiler Optimizations “undefined” Circular Structures Unique to Haskell

Think Functionally – Laziness

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

Think Functionally – Laziness

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

Think Functionally – Laziness

undefined 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)

Common Patterns – Future Topics “newtype”, “type”, ($), and Record Syntax Numeric Type Heirarchy and ByteStrings Monads Common Monads (I/O, Reader, Writer, State) MonadTransformers and MonadPlus Arrows Parser Combinators Category Theory and Advanced Types Advanced Functional Data Structures
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

Where to go to Learn More

Where to go to Learn More

Where to go to Learn More

Learn You a Haskell for Great Good! Real World Haskell Haskell Wikibook
3 2

1

Write Yourself a Scheme in 48 Hours

4

1 HTML: http://learnyouahaskell.com/ 2 HTML: http://book.realworldhaskell.org/ 3 HTML: https://secure.wikimedia.org/wikibooks/en/wiki/Haskell 4 HTML: http://halogen.note.amherst.edu/~jdtang/scheme_in_48/tutorial/ overview.html

Where to go to Learn More

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

1

#Haskell IRC Channel

HTML: http://hackage.haskell.org/ 2 HTML: http://haskell.org/hoogle/ 3 HTML: http://holumbus.fh-wedel.de/hayoo/hayoo.html 4 HTML: http://www.haskell.org/haskellwiki/IRC_channel

1

Thanks

Thanks

Thanks

Latex template and tech support: Daniel “paradigm” Thau For teaching me Haskell and providing some of my examples: BONUS, Learn You a Haskell Bryan O’Sullivan, Don Stewart, and John Goerzen, Real World Haskell

Sign up to vote on this title
UsefulNot useful