• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Haskell Tour (Part 1)
 

Haskell Tour (Part 1)

on

  • 4,246 views

We introduce Haskell. Why is it interesting. Where did it come from. What is it like. How to get started. ...

We introduce Haskell. Why is it interesting. Where did it come from. What is it like. How to get started.

We show a GHCi session. We introduce simple recursive function and data. And we demo QuickCheck for testing properties of automatically generated data.

Statistics

Views

Total Views
4,246
Views on SlideShare
3,372
Embed Views
874

Actions

Likes
7
Downloads
78
Comments
0

10 Embeds 874

http://codeaholics.hk 834
https://twitter.com 17
https://twimg0-a.akamaihd.net 8
http://feeds.feedburner.com 4
https://si0.twimg.com 4
http://posterous.com 3
http://webcache.googleusercontent.com 1
http://paper.li 1
http://a0.twimg.com 1
https://abs.twimg.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Haskell Tour (Part 1) Haskell Tour (Part 1) Presentation Transcript

    • HaskellA Whirlwind Tour William Taysom 2011
    • Haskell
    • HaskellWho?What?When?Where?Why?How?
    • HaskellWho?What?When?Where?Why?How?
    • Why? Aesthetics
    • Why? Aesthetics“We provided DARPA with a copy of our prototypeimplemented in Haskell without explaining that it wasa program, and based on preconceptions from theirpast experience, they had studied the program underthe assumption that it was a mixture of requirementsspecification and top level design. They wereconvinced it was incomplete because it did not addressissues such as data structure design and executionorder.” — Paul Hudak
    • Why? Aesthetics“Take Lisp: you know its the most beautiful languagein the world. At least up until Haskell came along.” — Larry Wall
    • Why? Aesthetics“Reading Haskell is like reading poetry.Writing Haskell is like writing poetry.” — Oliver Steele
    • Why? Aesthetics“I also have interest in Haskell, but my brain justexplodes every time I read a Haskell program biggerthan ten lines.” — Matz
    • Why? Aesthetics“The biggest advantage of Haskell to me is that it helpsme write better programs in other languages.” — Tenerife Skunkworks
    • Why? Aesthetics.NET LINQPython List ComprehensionsJava GenericsJavaScript jQuery
    • Why? Pragmatics
    • Why? PragmaticsPlatform Compiler Debugger Profiler TestingLibraries Network Graphics HackageCommunity Books Documentation Hoogle
    • Why? PragmaticsPlatform Compiler Debugger Profiler TestingLibraries Network Graphics HackageCommunity Books Documentation Hoogle
    • Why? Pragmatics Hoogle
    • Why? Pragmatics Hoogle
    • Why? PragmaticsPlatform Compiler Debugger Profiler TestingLibraries Network Graphics HackageCommunity Books Documentation Hoogle
    • Why? PragmaticsPlatform Compiler Debugger Profiler TestingLibraries Network Graphics HackageCommunity Books Documentation Hoogle
    • How? GHC Documentation Libraries Cabal Hackage
    • Why? PragmaticsPlatform Compiler Debugger Profiler TestingLibraries Network Graphics HackageCommunity Books Documentation Hoogle
    • Why? Pragmatics
    • Why? Pragmatics
    • Why? Pragmatics“A programming language must be considered in thecontext of its community, and Haskell has anexemplary one. I have come to believe, however, thatthis polite exterior conceals a deep and consumingmadness.” — Avdi Grimm
    • Why? Performance
    • Why? PerformanceThe Computer Language Benchmarks Game
    • Why? Performance Web Server Pong benchmark, extra large instance, requests/second
    • Why? Performance Web Server Pong benchmark, extra large instance, requests/second
    • Why? Aesthetics Pragmatics Performance
    • HaskellWho?What?When?Where?Why? Aesthetics Pragmatics PerformanceHow?
    • HaskellWho?What?When?Where?Why? Aesthetics Pragmatics PerformanceHow?
    • Who? When? Where? September 1987
    • Who? When? Where? Portland, Oregon
    • Who? When? Where?Functional ProgrammingLanguages and ComputerArchitecture Conference
    • Who? When? Where? A Dozen Purely Functional Languages
    • Who? When? Where? All Similar
    • Who? When? Where? Committee Formed
    • Who? When? Where? Committee Formed
    • Provide faster communication of newideas.Stable foundation for real applicationdevelopment.Vehicle through which others would beencouraged to use functional languages.
    • Who? When? Where?Haskell ReportApril 1st 1990“You know, Haskellactually never liked thename Haskell.” — Mary Curry
    • Who? When? Where? 2002Revised Haskell 98 Report
    • Who? When? Where? 2010 Haskell
    • HaskellWho? Research Wadler Hudak Peyton-JonesWhat?When? 1987 1990 2002 NowWhere? Portland Glasgow MicrosoftWhy? Aesthetics Pragmatics PerformanceHow?
    • HaskellWho? Research Wadler Hudak Peyton-JonesWhat?When? 1987 1990 2002 NowWhere? Portland Glasgow MicrosoftWhy? Aesthetics Pragmatics PerformanceHow?
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What? ProgrammingSource CodeFormal, Textural SyntaxStatic & Runtime SemanticsData, Variables, Lexical ScopeInterpreter, Compiler
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What? Functional (Not Imperative)
    • What? FunctionalImperative Statements Executed Step-by-step
    • What? FunctionalImperative Statements Executed Step-by-step Modifying State
    • What? FunctionalImperative Statements Executed Step-by-step Modifying State Turing Machine
    • What? FunctionalImperative Statements Executed Step-by-step Modifying State Von Neumann Architecture
    • What? FunctionalImperative Statements Executed Step-by-step Modifying State Von Neumann ArchitectureFunctional Expressions Recursively Simplified
    • What? FunctionalImperative Statements Executed Step-by-step Modifying State Von Neumann ArchitectureFunctional Expressions Recursively Simplified Reduced Value
    • What? FunctionalImperative Statements Executed Step-by-step Modifying State Von Neumann ArchitectureFunctional Expressions Recursively Simplified Reduced Value Lambda Calculus
    • What? FunctionalImperative Statements Executed Step-by-step Modifying State Von Neumann ArchitectureFunctional Expressions Recursively Simplified Reduced Value Lambda Calculus
    • What? FunctionalImperative Statements Executed Step-by-step Modifying State Von Neumann ArchitectureFunctional Expressions Recursively Simplified Reduced Value Lambda Calculus
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What? Pure (No Side Effects)
    • What? Pure Immutable Only
    • What? PureReferential Transparency
    • What? Pure Functions always return the same value. If v = f x, then you can always replace f x with v.
    • What? Pure Functions always return the same value. If v equals f x, then you can always replace f x with v.
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What? Non-strict Be lazy.
    • What? Non-strict Be lazy. Ignore evaluation order.
    • Wait...
    • if everything isimmutable and there are no side effectsand evaluation is lazy,
    • then how the hell do you do anything?
    • MONADS Bring your own Semicolon
    • What? Monads
    • What? Monads
    • What? Monads
    • What? Monads
    • What? Monads
    • What? Monads“Haskell is the worlds finestimperative programming language.” — Simon Peyton-Jones
    • What? Monads“Haskell is the only language I know withfirst-class support for imperative programming.” — SamB
    • What? Monads“Haskell has no preferred imperative semantics, andthe monad just lets you swap out the semanticsaccording to your needs.” — Jared Updike
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What? Types Strong Static Inference
    • What? Types Strong Static Inference
    • What? Strong Types Runtime values have types.
    • What? Strong Types Runtime values have types. like Java and Ruby unlike C and Assembly (Not Weak)
    • What? Types Strong Static Inference
    • What? Types Strong Static Inference
    • What? Static Types Source code expressions have types.
    • What? Static Types Source code expressions have types. like C and Java unlike Ruby and JavaScript (Not Dynamic)
    • What? Types Strong Static Inference
    • What? Types Strong Static Inference
    • What? Type InferenceAutomatically determines types of variables.
    • What? Type InferenceAutomatically determines types of variables. like C# and Go unlike C and Java (Not Manifest)
    • You don’t need to type the type!
    • SYNERGY Purity means types tell you a lot.
    • What? Type Purity No side effects mean,
    • What? Type Purity No side effects mean, argument and return types limit what a function can do.
    • What? Type Purity“Haskell is so strict about type safety that randomlygenerated snippets of code that successfully type checkare likely to do something useful, even if youve no ideawhat that useful thing is.” — sigfpe
    • What? Type Purity“Since when does "it compiles" equate to "it will run(correctly)"? Were talking about C, after all, notHaskell.” — Sean Russell
    • What? Types Strong Static Inference
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • What?A non-strict, purelyfunctional programminglanguage with strong,static type inference.
    • HaskellWho? Research Wadler Hudak Peyton-JonesWhat? Non-strict Purely Functional Static TypesWhen? 1987 1990 2002 NowWhere? Portland Glasgow MicrosoftWhy? Aesthetics Pragmatics PerformanceHow?
    • HaskellWho? Research Wadler Hudak Peyton-JonesWhat? Non-strict Purely Functional Static TypesWhen? 1987 1990 2002 NowWhere? Portland Glasgow MicrosoftWhy? Aesthetics Pragmatics PerformanceHow?
    • How? Just Download and Install the Platform
    • How? Just Download and Install the Platform
    • Glorious GlasgowHaskell Compilation System
    • GHCCompiler ghcInteractive ghciScripts runghc
    • GHCCompiler ghcInteractive ghciScripts runghc
    • HaskellWho? Research Wadler Hudak Peyton-JonesWhat? Non-strict Purely Functional Static TypesWhen? 1987 1990 2002 NowWhere? Portland Glasgow MicrosoftWhy? Aesthetics Pragmatics PerformanceHow? Platform Hoogle Hackage
    • HaskellWho? Research Wadler Hudak Peyton-JonesWhat? Non-strict Purely Functional Static TypesWhen? 1987 1990 2002 NowWhere? Portland Glasgow MicrosoftWhy? Aesthetics Pragmatics PerformanceHow? Platform Hoogle Hackage
    • Example
    • ┼ $ Example
    • $ ghci
    • $ ghciGHCi, version 7.0.2: http://www.haskell.org/ghc/ :? for helpLoading package ghc-prim ... linking ...done.Loading package integer-gmp ...linking ... done.Loading package base ... linking ...done.Loading package ffi-1.0 ... linking ...done.ghci>
    • $ ghciGHCi, version 7.0.2: http://www.haskell.org/ghc/ :? for helpLoading package ghc-prim ... linking ...done.Loading package integer-gmp ...linking ... done.Loading package base ... linking ...done.Loading package ffi-1.0 ... linking ...done.ghci> "hello, world"
    • $ ghciGHCi, version 7.0.2: http://www.haskell.org/ghc/ :? for helpLoading package ghc-prim ... linking ...done.Loading package integer-gmp ...linking ... done.Loading package base ... linking ...done.Loading package ffi-1.0 ... linking ...done.ghci> "hello, world""hello, world"ghci>
    • "hello, world"ghci>
    • "hello, world"ghci> 6 * 9
    • "hello, world"ghci> 6 * 942ghci>
    • "hello, world"ghci> 6 * 942ghci> [1, 2, 3]
    • "hello, world"ghci> 6 * 942ghci> [1, 2, 3][1,2,3]ghci>
    • "hello, world"ghci> 6 * 942ghci> [1, 2, 3][1,2,3]ghci> it
    • "hello, world"ghci> 6 * 942ghci> [1, 2, 3][1,2,3]ghci> it[1,2,3]ghci>
    • "hello, world"ghci> 6 * 942ghci> [1, 2, 3][1,2,3] application is so important in Haskell that “Functionghci> it it using the quietest possible syntax: we denote[1,2,3]at all.” nothingghci> reverse it — Simon Peyton-Jones
    • “Function application is so important in Haskell thatwe denote it using the quietest possible syntax:nothing at all.” — Simon Peyton-Jones
    • "hello, world"ghci> 6 * 942ghci> [1, 2, 3][1,2,3] application is so important in Haskell that “Functionghci> it it using the quietest possible syntax: we denote[1,2,3]at all.” nothingghci> reverse it — Simon Peyton-Jones
    • "hello, world"ghci> 6 * 942ghci> [1, 2, 3][1,2,3]ghci> it[1,2,3]ghci> reverse it[3,2,1]ghci>
    • [3,2,1]ghci>
    • [3,2,1]ghci> let xs = [1..100]
    • [3,2,1]ghci> let xs = [1..100]ghci>
    • [3,2,1]ghci> let xs = [1..100]ghci> xs
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]ghci>
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci>
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci> [x | x <- xs, x > 21]
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci> [x | x <- xs, x > 21][22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]ghci>
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci> [x | x <- xs, x > 21][22,23,⋯,99,100]ghci>
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci> [x | x <- xs, x > 21][22,23,⋯,99,100]ghci> filter (> 21) xs
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci> [x | x <- xs, x > 21][22,23,⋯,99,100]ghci> filter (> 21) xs[22,23,⋯,99,100]ghci>
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci> [x | x <- xs, x > 21][22,23,⋯,99,100]ghci> filter (> 21) xs[22,23,⋯,99,100]ghci> filter (x -> x > 21) xs
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci> [x | x <- xs, x > 21][22,23,⋯,99,100] TMTOWTDIghci> filter (> 21) xs[22,23,⋯,99,100]ghci> filter (x -> x > 21) xs[22,23,⋯,99,100]ghci>
    • TMTOWTDI
    • The Evolution of aHaskell Programmer1. Freshman 13. Continuation-passing2. Sophomore 14. Boy Scout3. Junior (Peano) 15. Combinatory4. Junior (Ban n+k) 16. List-encoding5. Senior (Leans Right) 17. Interpretive6. Senior (Leans Left) 18. Static7. Senior (Leans Around) 19. Beginning Graduate8. Memoizing 20. Origamist9. Points-free 21. Cartesianally-inclined10. Iterative 22. Ph.D.11. Iterative one-liner 23. Post-doc12. Accumulating 24. Tenured Professor
    • TMTOWTDI
    • [3,2,1]ghci> let xs = [1..100]ghci> xs[1,2,⋯,99,100]ghci> [x | x <- xs, x > 21][22,23,⋯,99,100] TMTOWTDIghci> filter (> 21) xs[22,23,⋯,99,100]ghci> filter (x -> x > 21) xs[22,23,⋯,99,100]ghci>
    • [22,23,⋯,99,100]ghci>
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci>
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci>
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci> divides 3 12
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci> divides 3 12Trueghci>
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci> divides 3 12Trueghci> 3 `divides` 12
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci> divides 3 12Trueghci> 3 `divides` 12Trueghci>
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci> divides 3 12Trueghci> 3 `divides` 12Trueghci> let divisors x = [d | d <- [1..x],d `divides` x]
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci> divides 3 12Trueghci> 3 `divides` 12Trueghci> let divisors x = [d | d <- [1..x],d `divides` x]ghci>
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci> divides 3 12Trueghci> 3 `divides` 12Trueghci> let divisors x = [d | d <- [1..x],d `divides` x]ghci> divisors 100
    • [22,23,⋯,99,100]ghci> let divides = x y -> rem y x == 0ghci> let divides x y = rem y x == 0ghci> divides 3 12Trueghci> 3 `divides` 12True Fundamentalsghci> let divisors x = [d | d <- [1..x],d `divides` x]ghci> divisors 100[1,2,4,5,10,20,25,50,100]ghci>
    • Fundamentals
    • Data Declarationdata Color = Red | Green | Blue
    • Variablesred = Red-- Lower case for variable and upper case forconstructor.nan = 0 / 0-- Variables stand for values. They do not labellocations.-- Dont need let because we arent at GHCi.-- Declarations go at top-level, not expressions.(Like Java, unlike Ruby.)
    • Functionshue Red = 0hue Green = 120hue Blue = 240
    • Lambda & Casehue = c -> case c of Red -> 0 Green -> 120 Blue -> 240
    • Pattern WildcardisRed Red = TrueisRed _ = False
    • Boolean Datadata Bool = True | False
    • Boolean Functionsotherwise = Truenot True = Falsenot False = True
    • Boolean OperatorsTrue && x = xFalse && _ = False(||) True _ = True(||) False x = x-- Parenthesis let us use operators prefix.
    • Operator Precedenceinfixr 3 &&infixr 2 ||-- Ten precedence levels: 0 binds least tightly, 9(default) binds most tightly.-- Three associativities: infixl (default), infixr,infix (non-associative).
    • Types“Types in Haskell express high-level design in the sameway that UML diagrams do in Object Orientedlanguages.” — Simon Peyton-Jones
    • Typesghci> :l example“Types in Haskell express high-level design in the sameway that UML diagrams do in Object Orientedlanguages.” — Simon Peyton-Jones
    • ghci> :l example[1 of 1] Compiling Main( example.hs, interpreted )Ok, modules loaded: Main.ghci>
    • ghci> :l example[1 of 1] Compiling Main( example.hs, interpreted )Ok, modules loaded: Main.ghci> :r
    • ghci> :l example[1 of 1] Compiling Main( example.hs, interpreted )Ok, modules loaded: Main.ghci> :rOk, modules loaded: Main.ghci>
    • ghci> :l example[1 of 1] Compiling Main( example.hs, interpreted )Ok, modules loaded: Main.ghci> :rOk, modules loaded: Main.ghci> :type red
    • ghci> :l example[1 of 1] Compiling Main( example.hs, interpreted )Ok, modules loaded: Main.ghci> :rOk, modules loaded: Main.ghci> :type redRed :: Colorghci>
    • ghci> :l example[1 of 1] Compiling Main( example.hs, interpreted )Ok, modules loaded: Main.ghci> :rOk, modules loaded: Main.ghci> :type redRed :: Colorghci> :t isRed
    • Typesghci> :l example[1 of 1] Compiling Main( example.hs, interpreted )Ok, :: Color loaded: Main. red modulesghci> Double nan :: :rOk, modules loaded: Main.ghci> Color -> Double hue :: :type redRed :: Color otherwise :: Boolghci> :t isRedisRed Bool -> Bool Bool not :: :: Color ->ghci> (||) :: Bool -> Bool -> Bool (&&),
    • Typesred :: Colornan :: Doublehue :: Color -> Doubleotherwise :: Boolnot :: Bool -> Bool(&&), (||) :: Bool -> Bool -> Bool
    • Recursive Datadata Color = Red | Green | Blue | Mix Color Color
    • Recursive Datadata Color = Red | Green | Blue | Mix Color Colormix :: Color -> Color -> Colormix = Mix-- Mix is a type constructor function.
    • Recursive Datayellow, cyan, magenta :: Coloryellow = Mix Red GreenMix cyan magenta = Mix (Mix Green Blue) (Mix Red Blue)-- Constructor functions can be used for patternmatching, but variables bind.
    • Recursive FunctionsisRed :: Color -> BoolisRed Red = TrueisRed (Mix c c) = isRed c && isRed cisRed _ = False
    • Recursive Functionshue :: Color -> Doublehue Red =0hue Green = 120hue Blue = 240
    • Recursive Functionshue :: Color -> Doublehue Red =0hue Green = 120hue Blue = 240hue (Mix c c) = ???
    • hue (Mix c c) = ???
    • hue (Mix c c) = ??? h
    • hue (Mix c c) = let h = hue c ??? h
    • hhue (Mix c c) = let h = hue c ??? h
    • hhue (Mix c c) = let h = hue c h = hue c ??? h
    • h mhue (Mix c c) = let h = hue c h = hue c ??? h
    • h mhue (Mix c c) = let h = hue c h = hue c m = average h h h ???
    • h mhue (Mix c c) = let h = hue c h = hue c m = average h h h average x y = abs (x + y) / 2 ???
    • h mhue (Mix c c) = let h = hue c h = hue c m = average h h h average x y = abs (x + y) / 2 in m
    • h mhue (Mix c c) = let h = hue c h = hue c m = average h h h average x y = abs (x + y) / 2 in ??!
    • mhue (Mix c c) = let h = hue c h = hue c m = average h h h average x y = abs (x + y) / 2 in ??! h
    • mhue (Mix c c) = let h = hue c h = hue c m = average h h h average x y = abs (x + y) / 2 in ??! h m
    • mhue (Mix c c) = let h = hue c h = hue c m = average h h h m = m + 180 average x y = abs (x + y) / 2 in ??! h m
    • m dhue (Mix c c) = let h = hue c h = hue c m = average h h h m = m + 180 average x y = abs (x + y) / 2 in ??! h m
    • m dhue (Mix c c) = let h = hue c h = hue c m = average h h h m = m + 180 d = distance h m average x y = abs (x + y) / 2 in ??! h m
    • m dhue (Mix c c) = let h = hue c h = hue c m = average h h h m = m + 180 d = distance h m average x y = abs (x + y) / 2 distance x y = abs (x - y) h m in ??!
    • m dhue (Mix c c) = let h = hue c h = hue c m = average h h h m = m + 180 d = distance h m average x y = abs (x + y) / 2 distance x y = abs (x - y) h m in case compare d 90 of LT -> m EQ -> ??! GT -> m
    • m dhue (Mix c c) = let h = hue c h = hue c m = average h h h m = m + 180 d = distance h m average x y = abs (x + y) / 2 distance x y = abs (x - y) h m in case compare d 90 of LT -> m EQ -> nan GT -> m
    • m dhue (Mix c c) = r where r = case compare d 90 of LT -> m EQ -> nan h GT -> m h = hue c h = hue c m = average h h m = m + 180 h m d = distance h maverage x y = abs (x + y) / 2distance x y = abs (x - y)
    • Testingtest-framework organize testsHUnit what you’re used toQuickCheck test properties with automatically generated data
    • QuickCheckprop_hue_bounds c = let h = hue c in isNaN h || 0 <= h && h < 360
    • QuickCheckprop_hue_bounds c = let h = hue c in isNaN h || 0 <= h && h < 360prop_hue_mix_reflexivity c = let h = hue c in isNaN h || hue (Mix c c) == h
    • QuickCheckprop_hue_bounds c = let h = hue c in isNaN h || 0 <= h && h < 360prop_hue_mix_reflexivity c = let h = hue c in isNaN h || hue (Mix c c) == hprop_hue_mix_commutativity c c = let h = hue (Mix c c) in isNaN h || hue (Mix c c) == h
    • QuickCheckghci> quickCheck prop_hue_mix_commutativityprop_hue_bounds c = let h = hue c in isNaN h || 0 <= h && h < 360prop_hue_mix_reflexivity c = let h = hue c in isNaN h || hue (Mix c c) == hprop_hue_mix_commutativity c c = let h = hue (Mix c c) in isNaN h || hue (Mix c c) == h
    • ghci> quickCheck prop_hue_mix_commutativity+++ OK, passed 100 tests.ghci>
    • ghci> quickCheck prop_hue_mix_commutativity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_mix_reflexivity
    • ghci> quickCheck prop_hue_mix_commutativity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_mix_reflexivity+++ OK, passed 100 tests.ghci>
    • ghci> quickCheck prop_hue_mix_commutativity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_mix_reflexivity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_bounds
    • ghci> quickCheck prop_hue_mix_commutativity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_mix_reflexivity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_bounds*** Failed! Falsifiable (after 3 tests):Mix (Mix Red Blue) (Mix Green Red)ghci>
    • ghci> quickCheck prop_hue_mix_commutativity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_mix_reflexivity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_bounds*** Failed! Falsifiable (after 3 tests):Mix (Mix Red Blue) (Mix Green Red)ghci> hue (Mix magenta yellow)
    • ghci> quickCheck prop_hue_mix_commutativity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_mix_reflexivity+++ OK, passed 100 tests.ghci> quickCheck prop_hue_bounds*** Failed! Falsifiable (after 3 tests):Mix (Mix Red Blue) (Mix Green Red)ghci> hue (Mix magenta yellow)360.0ghci>
    • hhue (Mix c c) = r where r = case compare d 90 of LT -> m EQ -> nan m m GT -> m h = hue c h = hue c m = average h h d h m = m + 180 d = distance h m
    • hhue (Mix c c) = r where r = case compare d 90 of LT -> m EQ -> nan m m GT -> m h = hue c h = hue c m = average h h d h m = normalize (m + 180) d = distance h m
    • hhue (Mix c c) = r where r = case compare d 90 of LT -> m EQ -> nan m m GT -> m h = hue c h = hue c m = average h h d h m = normalize (m + 180) d = distance h mnormalize h | h < 360 = h | otherwise = h - 360
    • hhue (Mix c c) = r where r = case compare d 90 of LT -> m EQ -> nan m m GT -> m h = hue c h = hue c m = average h h d h m = normalize (m + 180) d = distance h mnormalize h | h < 360 = h | otherwise = normalize (h - 360)
    • ghci> h hue (Mix c c) = r where r = case compare d 90 of LT -> m EQ -> nan m m GT -> m h = hue c h = hue c m = average h h d h m = normalize (m + 180) d = distance h mnormalize h | h < 360 = h | otherwise = normalize (h - 360)
    • ghci> quickCheck prop_hue_bounds m
    • ghci> quickCheck prop_hue_bounds+++ OK, passed 100 tests.ghci> m
    • QuickCheckprop_hue_mix_nothing c c = distance (hue c) (hue c) == 180 ==> isNaN (hue (Mix c c))
    • QuickCheckghci> quickCheck prop_hue_mix_nothingprop_hue_mix_nothing c c = distance (hue c) (hue c) == 180 ==> isNaN (hue (Mix c c))
    • QuickCheckghci> quickCheck prop_hue_mix_nothing*** Gave up! Passed only 23 tests.ghci>prop_hue_mix_nothing c c = distance (hue c) (hue c) == 180 ==> isNaN (hue (Mix c c))
    • QuickCheckprop_hue_mix_nothing c c = distance (hue c) (hue c) == 180 ==> isNaN (hue (Mix c c))
    • QuickCheckprop_hue_mix_nothing c c = distance (hue c) (hue c) == 180 ==> isNaN (hue (Mix c c))-- Can we easily find the complement of a color?
    • complement Red = ???complement Green = ???complement Blue = ???complement (Mix c c) = ???
    • complement Red = cyancomplement Green = ???complement Blue = ???complement (Mix c c) = ???
    • complement Red = cyancomplement Green = magentacomplement Blue = ???complement (Mix c c) = ???
    • complement Red = cyancomplement Green = magentacomplement Blue = yellowcomplement (Mix c c) = ???
    • complement Red = cyancomplement Green = magentacomplement Blue = yellowcomplement (Mix c c) = Mix ??? ???
    • complement Red = cyancomplement Green = magentacomplement Blue = yellowcomplement (Mix c c) = Mix (complement c ) (complement c )
    • QuickCheckprop_complement c = let h = hue c in not (isNaN h) ==> distance h (hue (complement c)) == 180
    • QuickCheckprop_complement c = let h = hue c in not (isNaN h) ==> distance h (hue (complement c)) == 180prop_hue_mix_complement c = isNaN (hue (Mix c (complement c)))
    • QuickCheckghci> quickCheck prop_complementprop_complement c = let h = hue c in not (isNaN h) ==> distance h (hue (complement c)) == 180prop_hue_mix_complement c = isNaN (hue (Mix c (complement c)))
    • ghci> quickCheck prop_complement+++ OK, passed 100 tests.ghci>
    • ghci> quickCheck prop_complement+++ OK, passed 100 tests.ghci> quickCheck prop_hue_mix_complement
    • ghci> quickCheck prop_complement+++ OK, passed 100 tests.ghci> quickCheck prop_hue_mix_complement+++ OK, passed 100 tests.ghci>
    • To be continued...
    • SummaryHaskell is functional.Haskell has types.QuickCheck is cool.
    • Preview: Infinite Listsprimes = sieve [2..] where sieve (p:xs) = p : sieve [x | x <- xs, rem x p /= 0]
    • Preview: IO (echo.hs)import System.Environment (getArgs)import Data.List (intercalate)main = do args <- getArgs putStrLn (intercalate " " args)
    • Preview: Parsers
    • Preview: Parse JSONdata Value = String String | Number Double | Object [(String, Value)] | Array [Value] | Bool Bool | Null
    • Preview: Parse JSONvalue = String <$>jsstring <|> Number <$>number <|> Object <$>commaGroup { pair } <|> Array <$>commaGroup [ value ] <|> Bool True <$ string "true" <|> Bool False <$ string "false" <|> Null <$ string "null"
    • Preview: Parse JSONpair :: Parser (String, Value)pair = do s <- jsstring sp_char_sp : v <- value spaces return (s, v)
    • To be continued...