第四章:元組、型別推斷和高階函式

夢飛發表於2017-02-24

1.元組():

元組不算是Haskell中用得最多的資料結構,因為我們可以自定義資料型別來達到更好的效果,但元組捕捉了乘積型別(Product)的本質:多元組的型別取決於組成元組的每個型別,總的型別個數等於每個元素的型別個數乘積。定義如下

data () = ()

data (,) a b = (,) a b
data (,,) a b c = (,,) a b c
data (,,,) a b c d = (,,,) a b c d
....
--最長的元組允許62個元素

(1,2,3) :: (Int, Float, Double)
  • 單元(Unit)型別:它的建構函式只有一個(),它代表不包含任何資訊的資料型別,所有()在記憶體中只有一個固定的位置,如果一個函式的值是(),那麼經過求值後,它不佔用額外的記憶體,只佔用一個指標

    enter image description here

  • 注意列表和元組的區別

    data [a] = a : [a] | []
    data (,) a b = (,) a b
    
    
    [1,2,3] :: [Int]
    ["hello", "world"] :: [String]
    [1,"wat"] :: ???                    --報錯,列表裡所有的元素型別必須一致
    (1, ''hello") :: (Int, String)
    

2.型別推斷:

編譯器可以根據原始碼推斷出程式執行中每一個繫結對應的型別,從而在編譯階段消除型別不匹配帶來的錯誤。例如如下的例子

--Fibonacci 數列
fibonacci :: Int -> Int
fibonacci :: (Eq a, Num a, Num a1) => a -> a1
--第二行為GHC型別推斷出的型別宣告
--當我們用第一行的型別宣告時,會發生意外,因為Int資料型別在機器上是有範圍限制的
--在沒有型別說明的情況下,編譯器總會挑選一個滿足要求的最通用的型別

fibonacci 1 = 1
fibonacci 2 = 1
fibonacci n = fibonacci (n-2) + fibonacci (n-1)  

enter image description here

所以我們用Haskell寫程式時,可以不用寫型別,編譯器可以根據程式碼自動推斷出所有繫結的型別

3.高階函式:

返回函式的函式被稱為高階函式

  • :k :kind 檢視型別函式(type function) 的類別(kind)。類別比型別高一個級別,他們是型別的型別 enter image description here 有哪些是型別函式??

  • 拉鍊(zip):zip和一種壓縮檔案的型別名稱一樣,顧名思義。把兩個列表拉成一個列表,按位置對應關係組成一個元組,長度為較短的那個

    zip :: [a] -> [b] -> [(a,b)]
    zip [] _ = []
    zip _ [] = []
    zip (x:xs) (y:ys) = (x,y) : zip xs ys
    

    enter image description here

  • zipWith: 把額外的一個函式“打包”進去

    zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    zipWith _ _ [] = []
    zipWith _ [] _ = []
    zipWith f (x:xs) (y,ys) = f x y : zipWith f xs ys
    

    enter image description here

  • 柯里化(Curry):源於著名的邏輯學家Haskell Curry

    curry :: ((a,b) -> c) -> a ->b -> c
    curry f x y = f (x,y)
    
    
    uncurry :: (a-> b  -> c) -> (a ->b) -> c
    uncurry f (x y) = f x y
    

    enter image description here

(max 4) 可以當作max 函式的一個部分應用

這裡感覺參考LEARN YOU A HASKELL FOR GREAT GOOD第6章高階函式更容易理解,或者下一章裡有講?

相關文章