如何编辑 Haskell 程序? 如何运行解释器? 如何在解释器下运行一个 Haskell 程序?. 类型和函数. 一个程序(函数)形如 f :: A -> B 或者 f :: A -> B -> C, A, B, C 表示函数的输入数据集合和输出数据集合 例如 , Int 表示整数集合 double :: Int -> Int mymax :: Int -> Int -> Int 问题: 如何表示输入数据和输出数据? Haskell 提供了哪些表示数据的类型? 如何定义函数,或者定义函数的语法如何?. 第二章 基本类型与定义. 本章介绍
Une image / un lien ci-dessous est fourni (tel quel) pour télécharger la présentation
Politique de téléchargement : le contenu du site vous est fourni TEL QUEL pour votre information et votre usage personnel ; il ne peut être vendu, concédé sous licence ni partagé sur d’autres sites sans l’accord de son auteur.Le contenu vous est fourni TEL QUEL, pour votre information et votre usage personnel uniquement.Téléchargez la présentation en cliquant sur ce lien.Lors du téléchargement, si vous ne parvenez pas à télécharger une présentation, l’éditeur a peut-être supprimé le fichier de son serveur.Pendant le téléchargement, si vous ne parvenez pas à obtenir une présentation, le fichier a peut-être été supprimé par l’éditeur.
类型和函数 • 一个程序(函数)形如 f :: A -> B 或者 f :: A -> B -> C, A, B, C 表示函数的输入数据集合和输出数据集合 • 例如, Int 表示整数集合 double :: Int -> Int mymax :: Int -> Int -> Int • 问题: 如何表示输入数据和输出数据?Haskell提供了哪些表示数据的类型? • 如何定义函数,或者定义函数的语法如何?
类型安全(Type Safety) 但是 是错误的, 称之为类型错误( type error). double True 所有的类型错误均可以在编译时发现,这使得函数程序是类型安全的: well-typed programs never go wrong (no errors at run time)!. 类型避免了一类错误的发生。
运算符 运算只是“中缀”函数. (+) :: Int -> Int -> Int 我们可以用两种方式使用+: (+) 3 2 = 5 3 + 3 = 5 一个二元函数也可以使用`(backquote)转变为中缀运算: 7 `div` 2 3 7 `mod` 2 1 Infix version of div and mod
重载(Overloading) 我们使用同一个符号(==)比较整数的相等,布尔值的相等,这也表明(==)具有下列类型: Int -> Int -> Bool Bool -> Bool -> Bool 这种现象称为重载(overloading): 使用同一个符号或者名表示不同类型上的(相似)运算. 更多的例子: (+), (-), (*) 等.
使用条件的定义 如何定义求两个整数中较大的数, max? max :: Int -> Int -> Int max x y | x >= y = x | otherwise = y 如果条件为True, 则max x y 等于 x 如果条件为 False, 那么 max x y 等于 y
An example using guards maxThree :: Int -> Int -> Int -> Int maxThree x y z | x >= y && x >= z = x | y >= z = y | otherwise = z Or using a predefined function: maxThree’ x y z = max (max x y) z Exercise: compute maxThree 6 (4+3) 5.
条件表达式 Haskell 提供下列条件表达式: if condition then m else n 其语义是, 如果条件condition (of type Bool) 的值为True, 则表达式的值为m, 否则为n, 其中m和n必须具有相同的类型. 例如, max x y = if x >= y then x else y Exercise. Define min :: Int -> Int -> Int
使用定义做计算 • 函数调用的计算过程 • 用函数定义的右式代替函数; • 使用实在参数代替形式参数 • double :: Int -> Int • double x = 2*x • double 3 2 *3 • 6
计算顺序 一个表达式的计算顺序可能有多种,但是,其计算结果不变. double 5 10 double (2+3) 2*(2+3) The evaluation order does not matter.
递归(Recursion) 能否用fac (n-1) 计算fac n? 问题: 定义函数fac :: Int -> Int fac n = 1 * 2 * … * n 假如我们已知fac (n-1),如何计算fac n? fac n = 1 * 2 * … * (n-1) * n = fac (n-1) * n
阶乘表 已知 fac 0 = 1. n fac n 0 1 1 1 2 2 3 6 4 24 ... 所以 fac 1 = 1 * 1. 所以 fac 2 = 1 * 2. 所以 fac 3 = 2 * 3.
Factorial的递归定义 递归基 fac :: Int -> Int fac 0 = 1 fac n | n > 0 = fac (n-1) * n 递归情况
计算 Factorials fac :: Int -> Int fac 0 = 1 fac n | n > 0 = fac (n-1) * n fac 4 ?? 4 == 0 False ?? 4 > 0 True fac (4-1) * 4 fac 3 * 4 fac 2 * 3 * 4 fac 1 * 2 * 3 * 4 fac 0 * 1 * 2 * 3 * 4 1 * 1 * 2 * 3 * 4 24
原始递归 • 原始递归定义规则: • 利用f (n-1)定义f n(n > 0). • 直接定义f 0. • 如何确定一个函数是否存在递归定义: • 可否将 f n 的计算转换为类似的 f (n-1)的计算,但是参数更简单; • 能否直接定义最简单的情况 f 0;
Quiz Define a function power so that power x n == x * x * … * x n times (Of course, power x n == x^n, but you should define power without using ^).
Quiz Define a function power so that power x n == x * x * … * x n times Don’t forget the base case! power x 0 = 1 power x n | n > 0 = power x (n-1) * x Since this equals (x * x * … * x) * x n-1 times
一般递归(General Recursion) 如何利用f x之值计算f n 之值, 其中 x小于n? Example x^(2*n) == (x*x)^n x^(2*n+1) == (x*x)^n * x
一般递归的幂函数 注意不要漏掉递归基 power :: Int -> Int -> Int power x 0 = 1 power x n | n `mod` 2 == 0 = power (x*x) (n `div` 2) | n `mod` 2 == 1 = power (x*x) (n `div` 2) * x 两种递归的情况 这个定义有何特点呢?
Comparing the Versions First Version power 3 5 power 3 4 * 3 power 3 3 * 3 * 3 power 3 2 * 3 * 3 * 3 power 3 1 * 3 * 3 * 3 * 3 power 3 0 * 3 * 3 * 3 * 3 * 3 1 * 3 * 3 * 3 * 3 * 3 243 Second Version power 3 5 power 9 2 * 3 power 81 1 * 3 power 81 0 * 81 * 3 1 * 81 * 3 243 4 function calls, 4 multiplications. 6 function calls, 5 multiplications.
函数类型 f :: A -> B e :: A F e :: B double是类型为Int -> Int的函数。 一般地, t1 -> t2 是将类型t1之值映射到类型t2的值的函数的类型。 double :: Int -> Int double x = x + x
Function types • 运算 “->” 是右结合的,即类型 t1 -> t2 -> t3 等于 t1 -> (t2 -> t3) • 但是, (t1 -> t2) -> t3 不可写成 t1 -> t2 -> t3
Curried functions add’ :: (Int, Int) -> Int add’ (x, y) = x + y add :: Int -> Int -> Int add x y = x + y Note: add 2 :: Int -> Int Uncurried version Curried version add 2 是一个函数
函数的复合 quadruple :: Int -> Int quadruple = double . double quadruple 3 double (double 3) double 6 12 函数的复合是函数上的运算
Is max correct? 程序设计是一个非常容易犯错误的过程 ;第一次设计的程序也很少是正确的。 软件开发很大一部分费用是找错和改错,即软件测试:给软件不同的输入,然后检查输出是否正确。 软件测试是确保软件符合设计要求的主要方法。
选择测试数据 测试数据尽可能包括各种可能的情形,特别是那些可能出现错误的情形,特殊情形和边界情形等。 函数 max 的测试数据至少应该包含 x<y, x==y, x>y, 以及正负参数组合的情形。 测试数据应该覆盖每一种情况,使每种情况都能运行至少一次。
规格说明与测试 我们可以定义检查一个性质是否成立的函数 prop_Max :: Int -> Int -> Bool prop_Max x y = x <= max x y && y <= max x y 如果性质prop_Max 总是返回 True, 那么规格说明是满足的。 我们可以测试许多输入x, y以检查max是否具有“正确性”性质,而无需检查max的结果是什么。