1 / 51

多元组和列表

多元组和列表. 多元组和列表具有很强的表达能力。我们将介绍 模式匹配 列表概括 多态函数. 多元组. 一个多元组由多个值构成,每个值称为多元组的分量。 例如 平面上的点 (x,y) 三维空间的点 (x,y,z) 购物项目 (”Wulong Tea”, 55) 不包含任何元素的元组 (). 多元组类型. 一个多元组类型说明每个分量的类型。 例如 (1,2) :: (Int, Int) (1.5, 2.25) :: (Float, Float) (”Wulong Tea”, 55) :: (String, Int) () :: () 单位类型. 类型定义.

conway
Download Presentation

多元组和列表

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 多元组和列表 多元组和列表具有很强的表达能力。我们将介绍 • 模式匹配 • 列表概括 • 多态函数

  2. 多元组 • 一个多元组由多个值构成,每个值称为多元组的分量。 • 例如 • 平面上的点(x,y) • 三维空间的点(x,y,z) • 购物项目(”Wulong Tea”, 55) • 不包含任何元素的元组()

  3. 多元组类型 一个多元组类型说明每个分量的类型。 例如 (1,2) :: (Int, Int) (1.5, 2.25) :: (Float, Float) (”Wulong Tea”, 55) :: (String, Int) () :: () 单位类型

  4. 类型定义 我们可以给多元组类型命名: type Purchase = (String, Int) Purchase和(String, Int) 可以互换: tea :: Purchase tea = (”Wulong Tea”, 55) 类型名以大写字母开始

  5. 模式匹配(Pattern matching) 多元组上的函数可以通过模式匹配定义。 例如,addPair (x, y) 返回x + y. addPair :: (Int, Int) -> Int addPair (x, y) = x + y 模式可以嵌套: shift :((Int, Int), Int) -> (Int, (Int, Int)) shift ((x, y), z) = (x, (y, z)) 一格模式,而不是一个简单变量

  6. 模式匹配 可以定义取得多元组某个分量的函数: name :: Purchase -> String name (s, i) = s price :: Purchase -> Int price (s, i) = i 一个模式必须与相应类型匹配.

  7. 标准选择函数 fst (x, y) = x snd (x, y) = y 但是,不可定义: select (x, y) 1 = x select (x, y) 2 = y 函数值类型不能依赖于参数的值。 它们的类型是什么?

  8. 列表(Lists) 一个列表由同类型的若干值构成,每个值称为列表的一个元素。 例如 [1, 2, 3] :: [Int] [True, False, True] :: [Bool] [] :: [Float] [(”Wulong Tea”, 55)] :: [Purchase]

  9. 多元组与列表 一个多元组有固定个数的元素构成,这些元素可以具有不同的类型。 一个列表由任意个数同类型元素构成。 列表类型上具有非常丰富的函数。 每当数据是由同类型的一系列元素构成时,考虑使用列表!

  10. 使用列表计数 [1..10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1,3..10] = [1, 3, 5, 7, 9] 例 fac :: Int -> Int fac n = product [1..n] 将列表元素相乘的标准函数

  11. 列表概括(List Comprehensions) 我们经常需要对列表元素施行同一种操作: 例如 doubles :: [Int] -> [Int] doubles xs = [2 * x | x <- xs] doubles [1..3] [2, 4, 6] 对xs中的每个元素 将2*x加到生成的列表上

  12. 求1至n的平方和 n [1, 2, 3, …, n] [1, 4, 9, …, n^2] 1 + 4 + 9 + … + n^2 sumsq :: Int -> Int sumsq n = sum [i^2 | i <- [1..n]]

  13. 过滤列表 列表概括可以包含一个或者多个条件,以过滤掉那些不满足条件的元素。 例如,求因子函数 factors :: Int -> [Int] factors n = [i | i <- [2..n], n `mod` i == 0] factors 12 [2, 3, 4, 6, 12] 只包含通过测试的元素

  14. 使用因子函数 计算因子个数: numFactors :: Int -> Int numFactors n = length (factors n) 测试素数: isPrime :: Int -> Bool isPrime n = factors n == [n] 列表长度函数, 返回列表元素个数

  15. 素数列表 我们可以列出小于某个数的所有素数: primes :: Int -> [Int] primes n = [x | x <- [2..n], isPrime x] primes 30 = [2,3,5,7,11,13,17,19,23,29]

  16. 列表概括的设计 每当你对列表元素逐个进行某个操作时使用列表概括。 一些条件测试 [ e | x <- list, test ] 表达式 称为生成器,x可以变量, 也可以是一个模式.

  17. 列表模式 每个列表示通过反复使用运算(:)构造的(读作cons), 其作用是在列表前添加一个元素。 [1,2,3,4] 等价于 1:( 2: (3: (4: []))) 空列表: [] 非空列表: x:xs

  18. 列表上的函数可以使用模式匹配: head :: [a] -> a head (x: xs) = x 或者 head (x:_) = x 例如, head [1,2,3] = 1

  19. tail :: [a] -> [a] tail (_:xs) = xs tail [1,2,3] = [2,3]

  20. 一个图书馆数据库的设计 任务:借阅信息存储到计算机上,并实现计算机管理(增加,删除,查询等) Alice Bush borrowed The Craft of Functional Programming Bob Clinton borrowed Million dollar baby!

  21. 借阅卡的表示 借阅卡包含那些信息? 借阅者名 Alice Bush borrowed The Craft of Functional Programming 书名 type Borrower = String type Book = String type Card = (Borrower, Book)

  22. 借阅卡文件表示 借阅卡文件由什么构成? -- 借阅卡序列! type Database = [Card] example :: Database example = [ (”Alice Bush”, ”The Craft of Functional Programming”), (”Bob Clinton”, ”Million Dollar Baby”) ]

  23. 查询数据库 我们希望从数据库中获得那些信息? books :: Database -> Borrower -> [Book] borrowers :: Database -> Book -> [Borrower] borrowed :: Database -> Book -> Bool numBorrowed :: Database -> Borrower -> Int 某人借阅的图书 某书是否借出 某人借阅的图书数

  24. Alice借了那些书? books example ”Alice Bush” = [”The Craft of Functional Programming”] books example ”David Gates” = [] books db person = [book | (borrower, book) <- db, borrower == person] 没有借书 使用模式匹配.

  25. 问题 定义: numBorrowed :: Database -> Borrower -> Int

  26. 定义 numBorrowed :: Database -> Borrower -> Int numBorrowed db person = length (books db person)

  27. 更新数据库 借书和还书均需要更新数据库 makeLoan :: Database -> Borrower -> Book -> Database returnLoan :: Database -> Book -> Database … 来计算修改后的 数据库 这些函数需要使用 更新前的库信息...

  28. 借书 makeLoan :: Database -> Borrower -> Book -> Database makeLoan db borrower book = [(borrower, book)] ++ db 增加新的借阅卡

  29. 还书 returnLoan :: Database -> Book -> Database returnLoan db book = [(borrower, book’) | (borrower, book’) <- db, book’ /= book]

  30. 列表的作用 记录序列随处可见,列表为此提供了一个建模工具 Haskell能够为列表提供很好的支持,是数据结构的第一选择 但是,列表有时效率不高

  31. 一些列表标准函数 Haskell 提供了许多标准列表函数。 length的类型是什么?

  32. 多态类型(Polymorphic Types) length 具有许多类型 其类型是多态的 (polymorphic). length :: [Int] -> Int length :: [Float] -> Int length :: [Card] -> Int 对于任意类型t, length :: [t] -> Int 一个类型变量 表示任意类型 类型变量 以小写字母开始

  33. Taking and Dropping • take n xs 返回xs的前n个元素, • drop n xs 返回xs除前n个元素外的所有元素. • 例 • take 3 (factors 12) [2, 3, 4] • drop 3 (factors 12) [6, 12]

  34. 问题 take 和drop 的类型是什么?

  35. 问题 take 和drop具有相同的多态类型. take, drop :: Int -> [a] -> [a] 例如 Int -> [Float] -> [Float] Int -> [String] -> [String] Not Int -> [Float] -> [String] a 表示同一个类型.

  36. The Zipper 有时我们需要将两个列表的对应元素配对: zip [ ”Alice” , ”Bob”, ”Mary” ] [ ”American”, ”American”, ”English” ] [ (”Alice”,”American”), (”Bob”,”American”), (”Mary”,”English”)]

  37. zip的类型 zip :: [a] -> [b] -> [(a, b)] 例 zip [1, 2, 3] [”a”, ”b”, ”c”] [(1,”a”), (2,”b”), (3,”c”)] 此例的类型zip :: [Int] -> [String] -> [(Int, String)]

  38. 例:求 x 在 xs 中的位置 position :: a -> [a] -> Int 例: position ”b” [”a”, ”b”, ”c”] 2 方法: 给列表每个元素标以位置号,然后查找给定的元素。

  39. 给列表元素标以位置号 [”a”, ”b”, ”c”] [(”a”,1), (”b”,2), (”c”,3)] zip [”a”, ”b”, ”c”] [ 1, 2, 3 ] [(”a”,1), (”b”,2), (”c”,3)] 使用zip xs [1..length xs]

  40. 查找合适的元素 选取查找元素出现的位置 positions x xs = [pos | (x’,pos) <- zip xs [1..length xs], x’ == x] positions ”b” [”a”, ”b”, ”c”] [2] 结果是列表 我们需要一个数

  41. 最后的函数 position :: a -> [a] -> Int position x xs = head [pos | (x’,pos) <- zip xs [1..length xs], x’ == x] 选取第一个元素.

  42. 计算路径长度 路径长度是多少?

  43. 点的表示 type Point = (Float, Float) distance :: Point -> Point -> Float distance (x, y) (x’, y’) = sqrt ((x-x’)^2 + (y-y’)^2) x- 和y-坐标.

  44. 路径的表示 Q S R P type Path = [Point] examplePath = [p, q, r, s] path length = distance p q + distance q r + distance r s

  45. 两个常用的函数 • init xs -- 不包括最后一个元素的列表, • tail xs – 不包括第一个元素的列表. • init [p, q, r, s] [p, q, r] • tail [p, q, r, s] [q, r, s] • zip … [(p,q), (q,r), (r,s)]

  46. 函数pathLength pathLength :: Path -> Float pathLength xs = sum [distance p q | (p,q) <- zip (init xs) (tail xs)] 例 pathLength [p, q, r, s] distance p q + distance q r + distance r s

  47. 原则 Question: 你需要一起遍历两个列表吗? Answer: 使用zip!

  48. 小结 • 列表可以表示任何元素序列 • 列表可以表示程序中的重复计算 • 列表的构造和丰富的多态列表函数便于列表的处理 • 每当处理元素序列时,考虑使用列表!

More Related