Learn You a Haskell for Great Good

Functional Programming Language

• 以数学公式的方式描述问题

``````total = 0
for(i=0;i<10;i++){
total = total+i
}
``````

``````sum[1...10]
``````

1. 首先创建一个`list = 1...10`
2. 然后将list作为sum的输入，带入到sum中计算，得到结果

Functional Programming background

• 1930s: Alonzo Church develops the lamda calculus, a simple but powerful theory of functions
• 1950s: John McCarthy develops Lisp, the first functional language, with some influences from the lamda calculus, but retaining variable assignments .

• 1960s: Peter Landin develops ISWIM, the first pure functional language, based strongly on the lambda calculus, with no assignments!
• 1970s: John Backus develops FP, a functional language that emphasizes high-order functions and reasoning about programs.
• 1970s: Robin Milner and other develop ML, the first modern functional language, which introduced type inference and polymorphic types(generic).
• 1970s ~ 1980s: David Turner develops a number of lazy functional languages, culminating in the Miranda system.

qucik sort:

``````f[] = []
f (x:xs) = f ys ++ [x] ++ f zs
where
ys = [a | a <- xs, a<= x]
zs = [b | b <- xs, b > x]

``````

概述

Haskell is a typed, lazy, pure, functional programming language. Everything in haskell is function

``````f (x) = x+x
doubleMe::(Num a)=>a->a
doubleMe x = x+x;

f(x) = x+1
doubleSmallNumber x = (if x > 100 then x else x*2)+1

f(x,y) = 2*x + 2*y
doubleXY x y = 2*x + 2*y
``````
• 字符常量:
``````conanO'Brien = "It's a-me, Conan O'Brien!"
``````
• 数组
``````numbers = [1,2,2,3,4,5,6]
``````
• 数组拼接
``````addNumbers = [1,2,3] ++ [3,2,1]
``````
• 入队
``````anotherStrings = "shit":["ask","hell"]
``````
• 索引函数，x为索引值
``````index x = [1,2,3,4,5,5] !! x
``````
• list比较，如果位数相同，则从第一个值开始向后比较
``````compareResult1 = [3,2,1] > [1,2,3] true
compareResult2 = [3,4,2] > [99,88] false
``````
• list方法
``````head ： 5

tail ： 2，3，1
listTail = tail[4,2,3,1]

last : 1
listLast = last [3,2,1]

init: 1,2,3
listInit = init [1,2,3,4]

length : 4
listLength = length [123,2,3,4]

``````

take返回前几个:1,2,3

``````listTake = take 3 [1,2,3,4,5,5]
``````

null检测数组是否为空

``````listNull = null[12,3]  false
listNull2 = null[]true
``````

maximum/minimum数组最大值

``````listMax = maximum [1,2,3]
listMin = minimum [3,2,1]
``````

sum数组求和

``````listSum = sum [1,2,3]
``````

elem数组是否包含某个元素

``````listEle = 4 `elem` [3,3,4,5,5]  true
``````

range

``````listRangeInteger = [1..20] 1,2,3,4,5,6...,20
listRangeString = ['a'..'z'] a,b,c,d..,z
listRangeEventInteger = [2,4..20]  2,4,6,8...,20
``````

``````listCycle10Integer = take 10 (cycle[1,2,3]) 1,2,3,1,2,3,1,2,3,1
listCycle10String = take 10 (cycle"LOL ") LOL LOL LO
``````

``````listRepeat10Integer = take 10 (repeat(4)) 4444444444
``````
• 集合

``````S = {2*x | x -> N, x <=10}
``````

``````collectioA = [x*2 | x <- [1..10]]
``````

1<=x<=10，2x>12，2x的集合

``````collectionB = [x*2 | x <- [1..10],2*x >= 12]
``````

50<=x<=100 && x % 7 == 3的集合

``````collectionC = [x | x <- [50..100],x `mod` 7 == 3]
``````

``````boomBangs list = [if x<10 then "BOOM" else "BANG" | x<-list,odd x]
``````

``````multiplyList = [x*y | x<-[2,5,10],y<-[3,6,9]]
``````

``````length' list = sum[1 | _<-list]
``````

_ 表示我们并不关心从 List 中取什么值，与其弄个永远不用的变量，不如直接一个 _。 这个函数将一个 List 中所有元素置换为 1，并且使其相加求和

``````removeNonUppercase list = [c | c<-list, c `elem` ['A'..'Z']]
``````
• Tuple 元组

Tuple类似hash map，但是有多个value

``````tupleA = ("jayson","code",28)
``````

tuple的长度是固定的，不能动态增减 fst 返回tuple的首项。 tupleHead = fst(8,11)

snd返回尾项

``````tupleTail = snd("jsyon",False)
``````

zip方法将k-v关联起来

``````zipValue1 = zip[1..3]["a","b","c"]
``````

zip不固定长度

``````zipValue2 = zip[1,2,4,5]["a","b"] (1,"a")(2,"b")
``````

zip不固定长度

``````zipValue3 = zip[1..]["a","n","c"] (1,"a")(2,"n")(3,"c")
``````

list 和 tuple

``````tupleList = [(a,b,c) | a<-[1..10],b<-[2..9],c<-[3..8],a^2+b^2==c^2]
``````

类型

• 变量类型

``````
ghci> :t 'a'
'a' :: Char

ghci> :t True
True :: Bool

ghci> :t "HELLO!"
"HELLO!" :: [Char]

ghci> :t (True, 'a')
(True, 'a') :: (Bool, Char)

ghci> :t 4 == 5
4 == 5 :: Bool

``````
• 函数类型

``````
removeNonUppercase :: [Char] -> [Char]
removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]

``````

``````
addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z

``````

Types : Integer, Float, Double, Bool, Char 类型首字母必须大写

• Type variables

``````

``````

• Typeclasses

``````ghci> :t (==)
(==) :: (Eq a) => a -> a -> Bool

``````

``````ghci> :t (>)
(>) :: (Ord a) => a -> a -> Bool

``````

“>”的参数类型取决于父类Ord 同理，ord包含了<, >, <=, >= 这几个接口

``````show1 = show 3  "3"

Main> :t (show)
(show) :: Show a => a -> String

``````

show的参数类型取决于show自己，而show这个typeclass包含的参数类型为所有 3 是Integer，在包含的范围之内，因此可以转换为string

``````read1 = read "True" || False  True

``````

``````read3 = read "3" :: Int
[1,2,3,4]

``````

Enum包含：

``````succ，pred，[1..3](range)

``````

``````Main> :t ([1..3])
([1..3]) :: (Enum t, Num t) => [t]

``````

函数

• 参数匹配（代数）
``````lucky2 :: (Integral a) => a -> String
lucky2 x = (if x==7 then "LuckNumber" else "wrongNumber")

``````

``````lucky :: (Integral a) => a -> String
lucky 7 = "Luck Number!"
lucky x = "wrong number!"

``````

``````sayMe :: (Integral a) => a -> String
sayMe 1 = "One!"
sayMe 2 = "Two!"
sayMe 3 = "Three!"
sayMe 4 = "Four!"
sayMe 5 = "Five!"
sayMe x = "Not between 1 and 5"

``````

• 求阶乘:
``````factorial :: (Integral a) => a -> a
factorial 0 = 1
factorial n = n * factorial (n - 1)

``````
• 两个向量相加:限制a类型为num
``````addVectors :: (Num a) => (a,a) -> (a,a) ->(a,a)
addVectors a b = (fst a+fst b, snd a+snd b)

``````

``````
addVectors2 :: (Num a) => (a, a) -> (a, a) -> (a, a)
addVectors2 (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)

``````

``````headVal :: [a] -> a
headVal [] = error "Can't call head on an empty list, dummy!"

``````

``````tell :: (Show a) => [a] -> String
tell [] = "The list is empty"
tell (x:[]) = "The list has one element: " ++ show x
tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y
tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y

``````

• list长度:用递归求数组长度
``````length'::(Num b) => [a] -> b
length' [] = 0
lenght' (_:xs) = length'(xs)+1

``````

``````sum' :: (Num a) => [a] -> a
sum' [] = 0
sum' (x:xs) = x + sum' xs

``````
• Guards

``````bmiTell :: (RealFloat a) => a -> String
bmiTell x
| x <= 18.5 = "You're underweight, you emo, you!"
| x <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| x <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise   = "You're a whale, congratulations!"

``````

guard 由跟在函数名及参数后面的竖线标志，通常他们都是靠右一个缩进排成一列。 一个 guard 就是一个布尔表达式，如果为真，就使用其对应的函数体。如果为假，就送去见下一个 guard，如之继续 注：bmiTell x和下一句间不能有空行

``````max' :: (Ord a) => a -> a -> a
max' a b
| a > b     = a
| otherwise = b

``````
• where
``````bmiTell2 :: (RealFloat a) => a -> a -> String
bmiTell2 weight height
| bmi <= skinny = "You're underweight, you emo, you!"
| bmi <= normal = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= fat    = "You're fat! Lose some weight, fatty!"
| otherwise     = "You're a whale, congratulations!"
where bmi = weight / height ^ 2
skinny = 18.5
normal = 25.0
fat = 30.0
``````

where必须定义在最后面，而且变量的名字必须排成竖行

• let-in
``````let-in允许在函数中的任意位置定义局部变量

calcBmis :: (RealFloat a) => [(a, a)] -> [a]
calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2]

``````
• case

case表达式：

``````case expression of pattern -> result
pattern -> result
pattern -> result
...