What is functional programming?

Download Report

Transcript What is functional programming?

函数程序设计
Functional Programming
http://sist.sysu.edu.cn/~qiaohy/FP2012/
乔 海燕
[email protected]
020-31981361
Important links
• All about the course:
http://sist.sysu.edu.cn/~qiaohy/FP2012
• All about Haskell:
http://haskell.org
课程安排与要求
•
•
•
•
每周四13~15节,2~13周;
地点:实验室B403
讲义:Haskell函数程序设计;
成绩评定:平时成绩50% + 期末成绩50%,
平时成绩包括
– 课堂参与;
– 课堂、课下作业;
函数程序设计简介
•
•
•
•
•
函数程序设计语言的历史背景
什么是函数程序设计
函数程序设计的特点
函数与类型
Hugs – 一个Haskell 解释器
简介
•
•
•
•
•
历史背景
什么是函数程序设计
函数程序设计的特色
函数与类型
Hugs – 一个Haskell 解释器
软件危机
• 如何应对计算机程序日益增加的规模和复
杂性 (LOC, line of code. Window 3.1(1992) 3million LOC,
Windows 2000 30-50million LOC).
• 如何降低开发软件和维护软件的费用
( maintenance can be up to 70%, including understanding,
debugging and modifying the code)
• 如何增强我们对于软件正确性的信心(The
European Ariane 5(1996), cost 10 years and $7billion, explode
after 40s in its maiden voyage; the floating point division in
the Pentium processor cost Intel around 470 million )
程序设计语言
一种解决办法是设计一种全新的语言:
• 编写的程序结构、内容简洁,语义清晰,
具有很高的抽象性;
• 支持软件的重用;
• 支持快速原型设计;
• 提供解决问题的工具;
• 支持和鼓励形式化验证。
函数程序设计语言较好地到达了上述目标。
历史背景
1920s–1940s:
and
Alonzo Church
Haskell Curry
developed lambda calculus(λ演算), 它是一个函数
的理论,也是串行计算的一个模型。
历史背景
1960s:
John McCarthy
develops the first functional language Lisp, influenced
by lambda calculus, but still with variable
assignments.
历史背景
• Late 1960s: Peter Landin develops ISWIM, the
first pure functional language, based strongly
on lambda calculus
• 1978 John Backus publishes FP, a functional
language that emphasized high-order functions
and calculating with programs.
• Mid1970s: Robin Milner develops ML, the
first of the modern functional languages,
which introduced type inference and
polymorphic types.
历史背景
• David Turner develops Miranda
• 1988: A committee of prominent researchers
publishes the first definition of Haskell, a
standard lazy functional language.
• 1999: The committee publishes the definition
of Haskell98
Introduction
•
•
•
•
•
历史背景
什么是函数程序设计
函数程序设计的特点
函数与类型
Hugs – 一个Haskell 解释器
什么是函数程序设计?
• C, Java, Ada and Pascal 是命令式( imperative )
语言: 一个程序时一些命令的序列,程序运行时
命令按顺序执行。关注的焦点: 如何 进行计算.
• 一个函数程序定义了如何将输入数据转换为输出
数据,它是一个表达式:程序的运行通过计算表
达式实现。关注焦点: 计算什么.
• 函数程序设计基于一种不同于其他程序设计语言
的程序观:一个程序是从输入到输出的函数,程
序的执行是表达式的计算,而非命令的执行。
Let the machine do machine’s work and let
the human do human’s work.
什么是函数程序设计 (2)
• 表达式由函数和基本值构成.
• 例: 计算从1至10 的和.
命令式语言:
total = 0;
for (I = 1; I<=10, I++)
total += I;
Haskell语言:
sum [1..10]
sum 是一个函数, [1..10]
表示1 至 10的整数.
简介
•
•
•
•
•
背景
什么是函数程序设计
函数程序的特点
函数与类型
Hugs – 一个Haskell 解释器
函数程序设计的特点
• 简洁、优美. 函数程序更简洁。例如: qsort.
• 容易理解
qsort [] = []
qsort (x:xs) = qsort less ++ [x] ++ qsort more
where less = [y | y <- xs, y < x]
more = [y | y <- xs, y >= x]
函数程序设计的特点(2)
• 无副作用,较少的错误. The result of a function
(no side effect) is determined by its input, and only by
its input. The result doesn’t depend on the evaluation
order. This eliminates a whole class of bugs in
imperative languages.
• 强类型. It is impossible to apply a function to a
boolean when you should apply it to an int. Bugs are
caught at compile-time, rather than run-time. This
also makes it less buggy.
Features of functional programming(3)
• 代码重用: Polymorphism enhance reusability.
For example, qsort can be used to lists of int,
lists of double, lists of any type that has < and
>= defined.
• 模块化: A good programming language
support modular programming, and this
requires good glue. Functional programming
provides two kinds of glue- higher order
functions and lazy evaluation.
Features of functional programming(4)
• 高阶函数 A higher order function can takes
functions as arguments and return a function.
• 惰性计算 Non-strict functional languages
have another powerful feature: they only
evaluate as much of the program as is required
to get the answer - this is called lazy
evaluation(惰性计算).
• See “Why functional programming matter?”
简介
•
•
•
•
•
背景
什么是函数程序设计
函数程序设计的特点
函数和类型
Hugs – 一个Haskell 解释器
值与表达式
一个值是一个数据:
2, 3.1415, “Alice”, …
一个表达式可以计算其值:
2+3, pi*r^2, -b + sqrt(b^2 – 4*a*c)/(2*a), …
operation
function
表达式: 由值、运算符和函数构成;
一个值是不可再计算其值的表达式.
定义和类型
• 一个类型是同类型值的集合,或者说,这
些值支持一组相同的运算。例如,整数的
集合Int,布尔值的集合Bool,图形的集合。
• 2 :: Int 读作“2 具有类型 Int”, 称之为类型
说明.
• 一个定义给一个特定类型的表达式赋予一
个名
area :: Int
说明值的类型
名称以小写字母
area = 3 * 4
开始
说明如何计算表达式的
值
函数与类型
• 一个函数具有一些输入 (arguments,
parameters) 并返回一个输出值(result).
• 设A是函数f的输入值集合,称之为f的定义
域(the domain of the function f).
• 设B是函数f 的结果值的集合,称之为f的值
域(the codomain of the function f.)
• 称f是从集合A到集合B的函数。
• 用 A -> B表示A到B的所有函数的集合 。 A
-> B成为函数f的类型。
函数定义
一个函数定义说明如何由输入计算输出。
函数名
double :: Int -> Int
double x = 2 * x
说明输入类型
和输出类型
参数
area :: Int -> Int -> Int
area l b = l * b
函数体说明如何由输入计
算结果
函数应用
• 在数学上,函数应用通常表示为函数名后
接包含在括号内的参数,如f(x, y), f (2, 4).
在Haskell中, 函数应用表示为函数名后接依
次用空格分隔的参数,如,f x y, f 2 4.
• 在Haskell中, 括号用于组织表达式,如
f 2 (2 + 2)
• 函数应用比其他运算符具有更高的优先级,
如 f 2 + 4 等价于 (f 2) + 4
函数程序
• 一个函数程序由一些函数和值构成。
• 一个函数通常是用其他函数定义的。
• 一个主函数计算整个程序在输入下的输出。
Your first Haskell program
使用一个文本编辑器编辑如下文本并存储为
FirstScript.hs:
{- My first Haskell script
FirstScript.hs
-}
-- size is define as an integer
size :: Int
size = 23 + 45
square :: Int -> Int
square n = n * n
double :: Int -> Int
double x = 2 * x
example :: Int
example = double (size – square (3 – 23))
注释
• -- 单行注释
• {- 多行注释
…
-}
脚本格式Layout
Haskell也使用 {,} 和 ; 组织定义. 但是,更多
的是使用版面格式规则。
基本规则: 如果新的一行开始于前一行的右边,
则新行是前一行说明(定义)的继续,否
则是另一个说明(定义)的开始。
例如,
fxy
= x + y +123
gx=f xx
简单规则 : 一系列的同层定义应该始于同一列。
Layout rule
max :: Int -> Int -> Int
max x y = if x>=y
then x else y
min :: Int -> Int -> Int
min x y = …
OK
max :: Int -> Int -> Int
max x y = if x>=y then
min :: Int -> Int -> Int
min x y = …
Not OK
Haskell中的命名
• 函数名和变量名以小写字母开始。
• 类型名和构造符名以大写字母开始。如 Int,
True.
• 保留字(Reserved words): case class data
default deriving do else if import in infix infixl
infixr instance let module newtype of then type
where
简介
•
•
•
•
•
背景
什么是函数程序设计
函数程序设计的特点
函数与类型
Hugs – Haskell 解释器
运行 Hugs
• Hugs 是 Haskell 的一个实现,它的 PC版本
和 Unix 版本均可在下列网站免费下载安装
www.haskell.org/hugs/
• 开始运行Hugs, 执行hugs FirstScript.hs
Main > (在这里你可以运行你的程序)
例如,
Main > double 23 – square (double 4)
- 18
Hugs 命令
•
•
•
•
•
•
:load first.hs 载入 Haskell 脚本 first.hs
:reload
重新载入最近载入的文件
:type e
显示 e的类型
:edit first.hs 编辑文件 first.hs
:?
列出 Hugs 命令
:quit
退出系统
Hugs 命令还可以缩写为命令的第一个字母,
如 :l 等价于 :load.
错误信息(Error messages)
• 语法错误(Syntax error):
Prelude> 2-(3-4))
ERROR: Syntax error in expression
• 程序错误(Porgram errors):
Prelude> 4 `div` (double 2 – 4)
Program error: [primDiviInt 4 0]
类型错误Type Error
Type error:
main> double square
ERROR: Type error in application
*** expression : double square
*** term
: square
*** type
: Int -> Int
*** does not match : Int
标准引导库
运行hugs时,我们会看到
Reading file: “C::\HUGS\lib\Prelude.hs”
标准引导库 Prelude.hs 包含一些常用的算术函
数和列表函数。
Haskell还提供一些其他标准函数库。
模块(Modules)
• 一个计算机软件由成千上万行定义(说明,
命令,语句)构成。为了开发和维护大规
模的软件,我们必须将一个软件系统分解
成为相对独立的、较小的程序,称之为模
块。
• 一个模块可以调用其他模块。
• 一个模块可以控制此模块输出那些定义。
• 一个Haskell 程序由一些模块构成,其中一
个称为 Main ,并输出一个值main.
模块 (2)
一个模块包含一系列Haskell定义.
模块名
module Bee where
import Ant
…
调用其他模块
模块体
作业:
1. 下载安装hugs
2. 编辑FirstScript.hs, 并调入hugs运行
3. 找到Prelude.hs, 试着运行一些函数
4. 在FirstScript.hs中加入更多的函数