360 likes | 372 Views
The Value of Everything But the Cost of Nothing. A Tutorial to Haskell. Shu-Chun "scw" Weng scw _AT_ csie _DOT_ org http://scw.tw/works/OSDCtw2007/slides.ppt. What’s The Title?. One of the famous epigrams in programming by Alan J. Perlis, the first recipient of the Turing Award.
E N D
The Value of Everything But the Cost of Nothing A Tutorial to Haskell Shu-Chun "scw" Weng scw _AT_ csie _DOT_ org http://scw.tw/works/OSDCtw2007/slides.ppt APA Center, Taipei
What’s The Title? • One of the famous epigrams in programming by Alan J. Perlis, the first recipient of the Turing Award. • One man's constant is another man's variable. • In English every word can be verbed. Would that it were so in our programming languages. • Origins from LISP programmers. APA Center, Taipei
Outline • Why Haskell? • What's Haskell? • Syntax • Sample code APA Center, Taipei
Why Haskell? • http://haskell.org They are all open source software! APA Center, Taipei
Why Haskell? • Pugs • Implementation of Perl 6 • darcs • Distributed, interactive, smart RCS • lambdabot • GHC APA Center, Taipei
Why Haskell? • Powered by Ph.D.! • http://haskell.org/haskellwiki/Research_papers APA Center, Taipei
Why Haskell? From freenode, #perl6, 2005/3/2 http://xrl.us/e98m 19:08 < malaire> Does pugs yet have system() or backticks or qx// or any way to use system commands? 19:08 < autrijus> malaire: no, but I can do one for you now. a sec 19:09 < malaire> ok, I'm still reading YAHT, so I won't try to patch pugs just yet... 19:09 < autrijus> you want unary system or list system? 19:09 < autrijus> system("ls -l") vs system("ls", "-l") 19:10 < malaire> perhaps list, but either is ok 19:11 < autrijus> \\n Bool pre system (Str)\ 19:11 < autrijus> \\n Bool pre system (Str: List)\ 19:11 < autrijus> I'll do both :) 19:11 < autrijus> done. testing. 19:14 < autrijus> test passed. r386. enjoy 19:14 < malaire> that's quite fast development :) 19:14 < autrijus> :) APA Center, Taipei
What’s Haskell? • Functional programming language • A Style of programming • A language that Supports and Encourages it • Specific WHAT to do, not HOW to do. • Pure • No assignment, no side effect • Less bug! • No more “Segmentation fault: 11 (core dumped)” • map f . map g = map (f . g) • f(x) + f(x) = 2 * f(x) • “Mutable variables eliminated from .NET” by Bill Taylor on 2007/04/01 APA Center, Taipei
What’s Haskell? • Higher order functions • Functions are also value • takeWhile isAlpha “only the first word” • greaterThan n =\x -> x > n • Lazy • [ 1 .. ] • primes = sieve [ 2 .. ] • sieve (p:xs) = p : sieve [ x | x <- xs, (x mod p) > 0 ] APA Center, Taipei
What’s Haskell? (Rice U.) Walid Taha: “Why do you put type annotations all over your functions?" Under grad. student: “They make the code more readable and the interface explicit." Walid Taha: “Well, they're too verbose, and you really should be able to tell the types easily by looking at them. And you should also learn how to deal with those type error messages.“ (Yale U.) Paul Hudak: “Stating the types explicitly is considered good coding style." Paul Hudak: “You should annotate all your functions with types." • Strongly typed • No type casting, no runtime type check • Except unsafeCoerce or unsafePerformIO • No union • But there is “Either Int Double” • Sometimes too hypercritical, but it pays • Type inference • Don’t have to maintain the type of variable ourself • Still can provide type-signature • For double check • Explicit interfacing APA Center, Taipei
What’s Haskell? • Haskell 98 Language Report on ’03 • QuickSort [] = [] • QuickSort (x:xs) = QuickSort [ y | y <- xs, y < x ] ++ [x] ++ QuickSort [ y | y <- xs, y > x] APA Center, Taipei
How to Run Haskell • Get GHC from http://haskell.org/ghc/ • $ ghc Main.hs • Main.hi • Main.c • a.out or Main.exe • $ ghci Main.hsPrelude Main> QuickSort [9, 4, 1, 2, 6][1,2,4,6,9] APA Center, Taipei
Goal • Write a Haskell program to solve following puzzle • Find paths in a n by n by n cube • From one corner block to the furthest one • Visit every block exactly once (Hamilton path) • 8-connected, i.e. each stop to neighbor block • One path? All paths? Number of paths? APA Center, Taipei
Syntax • Representing coordinates and paths • Pair (tuple) • (1, 1, 2) • fst (a, b) = a; snd (a, b) = b • List • [ R, U, L, F, R, D, L ] • Cons: 1: [ 2, 3] = [1, 2, 3] • head [1, 2, 3] =1; tail [1, 2, 3] = [2, 3] • [1, 2, 3] ++ [4, 5, 6] = [1, 2, 3, 4, 5, 6] • [ ‘O’, ‘S’, ‘D’, ‘C’ ] = “OSDC” APA Center, Taipei
Syntax • Functions on lists • [4, 5, 6] !!2=5 • take 3 [7, 8, 9, 10, 11, 12] = [7, 8, 9] • map (+3) [1, 2, 3] = [4, 5, 6] • filter isAlpha “a1 b2 c3”=“abc” • map uc “osdc”=“OSDC” • zip [1, 2, 3, 4, 5] [2, 4, 8, 16, 32] = [(1, 2), (2, 4), (3, 8), (4, 16), (5, 32)] • fiblist = 0:1: zipWith (+) fiblist (tail fiblist) WHAT THE F**K ARE YOU WRITING? APA Center, Taipei
Syntax • Mathematician writes function as f(x) • Haskell guys write it f x • Reserve parentheses for ordering • lisp is full of parentheses, please don’t do so in Haskell • Mathematicians write f(g(x)) • lisp programmers write (f (g x)) • Haskell guys write it f (g x) • Or, clearer, f $ g x • f(x, g(y)) => f x $ g y APA Center, Taipei
Syntax • Functions on lists • [4, 5, 6] !!2=5 • take 3 [7, 8, 9, 10, 11, 12] = [7, 8, 9] • map (+3) [1, 2, 3] = [4, 5, 6] • filter isAlpha “a1 b2 c3”=“abc” • map uc “osdc”=“OSDC” • zip [1, 2, 3, 4, 5] [2, 4, 8, 16, 32] = [(1, 2), (2, 4), (3, 8), (4, 16), (5, 32)] • fiblist = 0:1: zipWith (+) fiblist (tail fiblist) APA Center, Taipei
Syntax • Mathematicians also write f(g(x)) as (f。g)(x) • It’s troublesome to key in “。”, thus we use (f . g) x • cflowizeProgram = cflowize () . cflowOptimizeProgram . guarding () • doCompile doCflow = chainExpand . (if doCflow then cflowizeProgram else id) . third . third . tiMain2 . (if doCflow then cflowDesugarProgram else id) • main = interact (unlines . map reverse . lines)-- command “rev” on Unix system APA Center, Taipei
Syntax • How about write an ad-hoc function? • λ in the lambda-calculus • Written as \x -> … x … • map (\x ->3+ x) [1, 2, 3] = [4, 5, 6] • “+” is a infix operator but we usually write functions in prefix • (+) is prefix: (+) 12=1+2=3 • `f` is infix: 3`elem` [2, 3, 4] • \x ->3+ x =\x -> (+) 3 x = (+) 3= (+3) APA Center, Taipei
Syntax • “Variable” declaration? “let” it! Or define by “where.” • let size =3 count = size * size * size -1 start = (1, 1, 1) finish = (size, size, size)in … searching code … • test_in_range (x, y, z) = bounded x && bounded y && bounded zwhere bounded n = n >0&& n <= size • Note the indentation! APA Center, Taipei
Syntax • Control flow • No goto of course • if … then … else … • Always have else part since we are defining functions • case … of … -> …; … -> … • if b then do_this else do_that =case b of True -> do_this False -> do_that APA Center, Taipei
Syntax • Loop There is no loop! Recursive, please! • int sum(int n, int list[]){int s = 0;for(int i = 0; i < n; ++i) s += list[i];return s; } • sum [] =0sum (x:xs) = x + sum xs • sum = foldr (+) 0 APA Center, Taipei
8 Syntax • Strongly typed but didn’t see any “type” yet! • Thanks to type inference • Built-in types • Int, Double, Char, String = [Char] • (Int, Int, Int), [(Char, Double)] • Function type: Int -> Int -> Int • ~ Int -> (Int -> Int) • Polymorphic type: a b. (a, b) -> a APA Center, Taipei
Syntax • Type synonym • type Cursor = (Int, Int, Int) • type Trail = Set Cursor • type State = ([Move], Cursor, Trail) • Algebraic datatypes • data Move = L | R | U | D | F | Aderiving Show • chooses = [L, R, U, D, F, A] APA Center, Taipei
Syntax • Polymorphic? Isn’t it template/generic? • fst (a, b) = a; fst :: (a, b) -> a • head (x:xs) = x; head :: [a] -> a • Cannot manipulate generic data! • Except that data is in some “class” • toString :: Show a => a -> StringtoString x =“(”++ show x ++“)” • Function show provided by class Show • class Show t where show :: t -> String APA Center, Taipei
Syntax • How to tell the world that our “move” can be shown? • Instance it! • data Move = … deriving Show • instance Show Move where show L =“L” show R =“R” … APA Center, Taipei
Syntax • Ok, we’ve told the world that our “move” can be shown, but how to really “tell” the world? • I/O is terrible in traditional functional language! *non-pure* • Monad! • putStr :: String -> IO ( ) • print :: Show a => a -> IO ( ) APA Center, Taipei
Syntax • Monad is MORE than IO • Maybe, Error, Continuation • List • single_step :: [State] -> [State] • single_step states =do (path, cursor, trail) <- states guard (cursor /= finish) next <- choices APA Center, Taipei
Sample Code • single_step :: [State] -> [State] • single_step states =do (path, cursor, trail) <- states guard (cursor /= finish) next <- choiceslet new_path = next:path new_cursor = move_cursor cursor next new_trail = Set.insert new_cursor trail guard (test_in_range new_cursor) guard (test_no_collision new_cursor trail) return (new_path, new_cursor, new_trail) APA Center, Taipei
Sample Code • Move cursor? Pattern matching! • move_cursor :: Cursor -> Move -> Cursormove_cursor (x, y, z) L = (x+1, y, z)move_cursor (x, y, z) R = (x-1, y, z)move_cursor (x, y, z) U = (x, y+1, z)move_cursor (x, y, z) D = (x, y-1, z)move_cursor (x, y, z) F = (x, y, z+1)move_cursor (x, y, z) A = (x, y, z-1) APA Center, Taipei
Sample Code • Ready to derive the solution? • solutions :: [[Move]]solutions = map keep_path $ foldr ($) initial all_stepswhere initial = [([], start, Set.singleton start)] all_steps = replicate count single_step keep_path (path, _, _) = path • Fold! • foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...) • replicate :: Int -> a -> [a] APA Center, Taipei
Sample Code • main :: IO () • Print all solutions • main = mapM_ print solutions • Print one solution • main = print $ head solutions • Print number of solutions • main = print $ length solutions • http://scw.tw/works/OSDCtw2007/Main.hs APA Center, Taipei
Further Reading • YAHT http://en.wikibooks.org/wiki/Haskell/YAHT • All about monadhttp://www.haskell.org/all_about_monads/html/index.html • The Essence of Functional Programming http://homepages.inf.ed.ac.uk/wadler/papers/essence/essence.ps • irc.freenode.org #haskell • GHC libraryhttp://www.haskell.org/ghc/docs/latest/html/libraries/index.html APA Center, Taipei
Q? APA Center, Taipei
Thanks ! APA Center, Taipei
Performance • Vanilla sieve • primes = sieve [ 2 .. ] • sieve (p:xs) = p : sieve [ x | x <- xs, (x mod p) > 0 ] • Less tests • primes = sieve [ 2 .. ] • sieve (p:xs) = p : sieve [ x | x <- xs, notFactorIn primes squares x] • noFactorIn (p:ps) (q:qs) x = q > x || x mod p > 0 && noFactorIn ps qs x • squares = [p * p | p <- primes] • 66% faster for P100, 90% for P1000, 94% for P5000 APA Center, Taipei