《Two Dozen Short Lessons in Haskell》学习(九)- Types of Curried Forms and Higher Order Functions

《Two Dozen Short Lessons in Haskell》(Copyright © 1995, 1996, 1997 by Rex Page,有人翻译为Haskell二十四学时教程,该书如果不用于赢利,可以任意发布,但需要保留他们的copyright)这本书是学习 Haskell的一套练习册,共有2本,一本是问题,一本是答案,分为24个章节。在这个站点有PDF文件。几年前刚开始学习Haskell的时候,感觉前几章还可以看下去,后面的内容越来越难以理解。现在对函数式编程有了一些了解后,再来看这些题,许多内容变得简单起来了。

初学Haskell之前一定要记住:

把你以前学习面向过程的常规的编程语言,如Pascal、C、Fortran等等统统忘在脑后,函数式编程完全是不一样的编程模型,用以前的术语和思维来理解函数式编程里的概念,只会让你困惑和迷茫,会严重地影响你的学习进度。

这个学习材料内容太多,想把整书全面翻译下来非常困难,只有通过练习题将一些知识点串起来,详细学习Haskell还是先看其它一些入门书籍吧,这本书配套着学学还是不错的。

 

第九章 柯里函数和高阶函数

从这一章起,开始遇到一些普通编程思维比较难以理解的概念。

关于高阶函数和柯里函数在这里《Haskell趣学指南》里介绍得挺清楚,引用如下:

haskell中的函数可以作为参数和返回值传来传去,这样的函数就被称作高阶函数。高阶函数可不只是某简单特性而已,它贯穿于haskell的方方面面。

在维基百科里关于柯里化Currying的解释:

在计算机科学中,柯里化(Currying),又称部分求值(Partial Evaluation),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

这样的解释还是太学术化了,比较难以理解。在这篇博文中关于max 5 6函数的理解还是相对比较容易的。

max 5 6这个函数可以理解为(max 5) 6这样的函数,如果定义一个函数g = max 5,那么g 6与max 5 6就是等价的了,经过这么一番折腾,可以看出每个函数实质上都可以看作为一个参数的函数。max 5 6看上去是2个参数,但实际上可以转化为g 6这样一个参数的函数,而函数g是max 5这样一个函数,也只有一个参数。

对于max 5这样古怪的函数是通常的编程语言最难理解的部分,有些人翻译为不全调用,需要仔细体会。

 

1 Suppose functions f and g have types Char -> String and String -> [String], respectively.

Then their composition g . f has type

a Char -> String

b Char -> String -> [String]

c Char -> [String]

d [[String]]

 

2 Suppose the type of a function f is f :: String -> String -> Bool. Then the type of f "x" is

a Bool

b String

c String -> Bool

d Nothing — f "x" is not a proper formula

 

3 Suppose the type of a function f is f :: Char -> String -> [String] -> [[String]].

Then f ’x’ and f ’x’ "y" have, respectively, types

a [String] -> [[String]] and [[String]]

b Char -> String -> [String] and Char -> String

c String -> [String] -> [[String]] and [String] -> [[String]]

d Nothing — f ’x’ is not a proper formula

 

4 Because the arrow notation is right associative, the type a -> b -> c has the same meaning as

a (a -> b) -> c

b a -> (b -> c)

c (a -> b -> c)

d a -> b (-> c)

 

5 The composition operator has type (.) :: (a -> b) -> (c -> a) -> (c -> b). Another way to express this type is

a (.) :: a -> b -> (c -> a) -> (c -> b)

b (.) :: (a -> b) -> (c -> a) -> c -> b

c (.) :: a -> b -> c -> a -> (c -> b)

d (.) :: a -> b -> c -> a -> c –> b

 

6 The composition operator has type (.) :: (a -> b) -> (c -> a) -> (c -> b). Another way to express this type is

a (.) :: (b -> c) -> (a -> b) -> (a -> c)

b (.) :: (a -> c) -> (b -> a) -> (b -> c)

c (.) :: (c -> a) -> (b -> c) -> (b -> a)

d all of the above

 

7 A function whose type is (a -> b) -> c must be

a lower order

b middle order

c higher order

d impossible to define

 

8 If a function f has type f :: a -> a, then the formulas f ’x’ and f True have, respectively, types

a Char and Bool

b [Char] and [Bool]

c Char -> Char and Bool -> Bool

d cannot be determined from given information

 

=========================================================

=========================================================

1 c

(g . f) x = g (f x)

f x把Char变为String,g (f x)再把String变为[String],那么(g . f)的类型就是Char –> [String]

 

2 c

3 c

4 b

一直对这个箭头不理解,看到现在突然醒悟了,这个箭头就理解为函数就行了,箭头的左边是输入类型,右侧是输出类型。

如果f的类型 a -> b -> c,实际上应该是这样理解为 a -> (b -> c),输入参数是a,输出类型是(b -> c),把它看成一个整体,即输出本身是一个函数,也就是说f a的类型是b -> c,说多了还真是拗口,这种不全函数的奥秘需要慢慢体会。

5 b 

(.)函数相当神奇,一开始理解还真需要下点功夫。

这个函数输入是2个函数,输出又是一个函数,相当于函数的传递。

函数g把c变为a,函数f把a变为b,那么函数(f . g)就把c变为b

写出来就是 (a->b) -> (c->a) -> (c->b)

           对应于f       对应于g

6 d

函数声明中a,b,c就是一种代号,保持对应关系即可,不一定非要写a。

 

7 c

第一个参数是(a->b),是个函数,所以肯定是高阶函数

 

8 a

对于f 'x',这时的a就是Char类型了,所以f 'x'类型就是Char

对于f True,这时的a就是Bool类型了,所以f True类型就是Bool

 

 

《Two Dozen Short Lessons in Haskell》学习(一)Hello World

《Two Dozen Short Lessons in Haskell》学习(二)Definitions

《Two Dozen Short Lessons in Haskell》学习(三)How to Run Haskell Programs

《Two Dozen Short Lessons in Haskell》学习(四)List Comprehensions

《Two Dozen Short Lessons in Haskell》学习(五)Function Composition and Currying

《Two Dozen Short Lessons in Haskell》学习(六)Patterns of Computation – Composition, Folding, and Mapping

《Two Dozen Short Lessons in Haskell》学习(七)- Types

《Two Dozen Short Lessons in Haskell》学习(八)- Function Types, Classes, and Polymorphism

《Two Dozen Short Lessons in Haskell》学习(九)- Types of Curried Forms and Higher Order Functions

《Two Dozen Short Lessons in Haskell》学习(十)- Private Definitions — the where-clause

《Two Dozen Short Lessons in Haskell》学习(十一)- Tuples

《Two Dozen Short Lessons in Haskell》学习(十二) 数值相关的类

《Two Dozen Short Lessons in Haskell》学习(十三)迭代及重复的常规模式

《Two Dozen Short Lessons in Haskell》学习(十四)截断序列和惰性求值

《Two Dozen Short Lessons in Haskell》学习(十五)- Encapsulation — modules

《Two Dozen Short Lessons in Haskell》学习(十六)- Definitions with Alternatives

《Two Dozen Short Lessons in Haskell》学习(十七) - 模块库

《Two Dozen Short Lessons in Haskell》学习(十八) - 交互式键盘输入和屏幕输出

《Two Dozen Short Lessons in Haskell》学习(十九) - 文件输入与输出

《Two Dozen Short Lessons in Haskell》学习(二十)- 分数

《Two Dozen Short Lessons in Haskell》学习(二十一)- 在形式参数中使用模式匹配

《Two Dozen Short Lessons in Haskell》学习(二十二)- 递归

第23章没有习题。

《Two Dozen Short Lessons in Haskell》(二十四)代数类型

posted @ 2012-11-27 20:35  申龙斌的程序人生  阅读(1373)  评论(0编辑  收藏  举报