12 Haskell
ftp://web.ntnu.edu.tw/WWW/func_prog/ghc zip ftp://web.ntnu.edu.tw/WWW/func_prog/ghc zip Haskell is Lazy evaluated Case-sensitive Purely functional
Lazy evaluated No computation takes place unless it is forced to take place when the result of that computation is used Pseudo-code List makeList() { List current = new List(); current.value = 1; current.next = makeList(); return current; } It attempt to get a value out of it. This leads to an infinite loop Hashall makeList = 1 : makeList 把 makelist 定義為 element1 加上 makelist
Purely functional Functions that do not have side effects are called pure If you have a value x you must not think of x as a register, a memory location or anything else of that nature x is simply a name, just as “Mary” is your name You cannot arbitrarily decide to store a different person in my name any more than you can arbitrarily decide to store a different value in x A call like x = x + 1 is called destructive Destructive update does not exist in Haskell
Prelude> sum [1..10] 55 Prelude> 5+2*3 11 Prelude> sin Prelude> length [1,5,9,3] 4 Prelude> reverse [1..10] [10,9,8,7,6,5,4,3,2,1]
Prelude> let pi = Prelude> pi The missing digits are just skipped when displaying the value Prelude> pi * 5^ Prelude> pi * 25^ Prelude> let r = 25.0 Prelude> let area = pi * r ^ 2 Prelude> area
Prelude> (5,3) (5,3) The first element of a pair need not have the same type as the second element Prelude> fst (5, "hello") 5 Prelude> snd (5, "hello") "hello“ Exercise Use a combination of fst and snd to extract the character out of the tuple ((1,’a’),"foo")
The primary limitation of tuples hold only a fixed number of elements: pairs hold two, triples hold three, and so on List Hold an arbitrary number of elements Prelude> [1,2] [1,2] Prelude> [1,2,3] [1,2,3]
: cons Prelude> 0:[1,2] [0,1,2] Prelude> 5:[1,2,3,4] [5,1,2,3,4] Prelude> 5:1:2:3:4:[] [5,1,2,3,4] If we write something using the [5,1,2,3,4] notation, the compiler simply translates it to the expression using (:) and []
Tuples are heterogeneous Lists must be homogenous Prelude> [(1,1),(2,4),(3,9),(4,16)] [(1,1),(2,4),(3,9),(4,16)] Prelude> ([1,2,3,4],[5,6,7]) ([1,2,3,4],[5,6,7]) Prelude> length [1,2,3,4,10] 5 Prelude> head [1,2,3,4,10] 1 Prelude> length (tail [1,2,3,4,10]) 4
String is simply a list of Chars Prelude> ’H’:’e’:’l’:’l’:’o’:[] "Hello“ ++ Prelude> "Hello " ++ "World“ "Hello World“ Prelude> "Five squared is " ++ show (5*5) "Five squared is 25"
Map Takes as arguments a list of values and a function that should be applied to each of the values Prelude> map Char.toUpper "Hello World“ "HELLO WORLD“ Filter Remove certain elements from a list depending on their value Prelude> filter Char.isLower "Hello World“ "elloorld“ Foldr Replaces occurences of the list cons operator (:) with the function parameter and replaces the empty list constructor ([]) with the initial value Prelude> foldr (+) 0 [3,8,12,5] 28
Prelude> foldr (*) 1 [4,8,5] 160 Prelude> foldr (-) 1 [4,8,5] 0 foldr (-) 1 [4,8,5] ==> 4 - (foldr (-) 1 [8,5]) ==> 4 - (8 - foldr (-) 1 [5]) ==> 4 - (8 - (5 - foldr (-) 1 [])) ==> 4 - (8 - (5 - 1)) ==> 4 - (8 - 4) ==> ==> 0
Foldl Goes the other way and effectively produces the opposite bracketing Prelude> foldl (+) 0 [3,8,12,5] 28 Prelude> foldl (-) 1 [4,8,5] -16 foldl (-) 1 [4,8,5] ==> foldl (-) (1 - 4) [8,5] ==> foldl (-) ((1 - 4) - 8) [5] ==> foldl (-) (((1 - 4) - 8) - 5) [] ==> ((1 - 4) - 8) - 5 ==> ((-3) - 8) - 5 ==> (-11) - 5 ==> -16
Exercise Use map to convert a string into a list of booleans, each element in the new list representing whether or not the original element was a lower-case character.That is, it should take the string “aBCde” and return [True,False,False,True,True].
test.hs module Test where x = 5 y = (6, "Hello") z = x * fst y Prelude> :l Test.hs Test> Test> x 5 Test> y (6,"Hello") Test> z 30
main = putStrLn "Hello World“ C:\ghc> ghc –make c:\\xxx\\test.hs -o test.exe or Prelude> :! ghc --make c:\\xxx\\test.hs -o test.exe C:\ghc> test.exe Hello World
Test.hs module Test -- 注意大寫 where sig x = if x < 0 -- 注意縮排 then -1 else if x > 0 then 1 else 0 Test> sig 5 1 Test> sig 0 0 Test> sig (5-10) -1 Test> sig (-1) -1
f x = case x of 0 -> 1 1 -> 5 2 -> 2 _ -> -1 f x = case x of { 0 -> 1 ; 1 -> 5 ; 2 -> 2 ; _ -> 1 } f x = case x of { 0 -> 1 ; 1 -> 5 ; 2 -> 2 ; _ -> 1 } f 0 = 1 f 1 = 5 f 2 = 2 f _ = -1
Test.hs module Test where -- 注意縮排 signum2 x = if x < 0 then -1 else if x > 0 then 1 else 0 f x = case x of 0 -> 1 1 -> 5 2 -> 2 _-> -1 Prelude > (sig. f) 2 1
roots a b c = let det = sqrt (b*b - 4*a*c) in ((-b + det) / (2*a), (-b - det) / (2*a)) roots a b c = let det = sqrt (b*b - 4*a*c) twice_a = 2*a in ((-b + det) / twice_a, (-b - det) / twice_a)
Imperative version int factorial(int n) { int fact = 1; for (int i=2; i <= n; i++) fact = fact * i; return fact; } int factorial(int n) { if (n == 1) return 1; else return n * factorial(n-1); } Haskell factorial 1 = 1 factorial n = n * factorial (n-1)
Exercise exponent a 1 = a exponent a b = a * exponent a (b-1)
Test.hs module Name where import IO name = do --do specifies the order of operations hSetBuffering stdin LineBuffering putStrLn "Please enter your name: " name <- getLine putStrLn ("Hello, " ++ name ++ ", how are you?") Name > name Please enter your name: Mary Hello, Mary, how are you? Name>
Prelude > (\x->2*x) 2 Prelude> map (\x -> x*x) [1..10] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] square = \x -> x*x f = \x y -> 2*x + y
Guess.hs module Main where import IO import Random main = do hSetBuffering stdin LineBuffering num <- randomRIO (1::Int, 100) putStrLn "I’m thinking of a number between 1 and 100" doGuessing num doGuessing num = do putStrLn "Enter your guess:" guess <- getLine let guessNum = read guess if guessNum < num then do putStrLn "Too low!" doGuessing num else if guessNum> num then do putStrLn "Too high!" doGuessing num else do putStrLn "You Win!"