《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还是先看其它一些入门书籍吧,这本书配套着学学还是不错的。
1 Guards in function definitions
a hide the internal details of the function from other software components
b remove some of the elements from the sequence
c select the formula that delivers the value of the function
d protect the function from damage by cosmic rays
2 The formula map reverse ["able", "was", "I"] delivers the value
a ["I", "saw", "elba"]
b ["elba", "saw", "I"]
c ["I", "was", "able"]
d ["able", "was", "I", "not"]
3 The formula map f xs delivers the value
a f x
b [f x | x <- xs]
c f xs
d [f xs]
4 Which of the following formulas is equivalent to the formula [g x y | y <- ys] ?
a (map . g x) ys
b (map g x) ys
c map (g x y) ys
d map (g x) ys
5 The following function delivers
HASKELL DEFINITION • h xs
HASKELL DEFINITION • | xs == reverse xs = "yes"
HASKELL DEFINITION • | otherwise = "no"
a "yes", unless xs is reversed
b "yes" if its argument is a palindrome, "no" if it’s not
c "no" if xs is not reversed
d "yes" if its argument is written backwards, "no" if it’s not
6 The following function
HASKELL DEFINITION • s x
HASKELL DEFINITION • | x < 0 = -1
HASKELL DEFINITION • | x == 0 = 0
HASKELL DEFINITION • | x > 0 = 1
a the value of its argument
b the negative of its argument
c a code indicating whether its argument is a number or not
d a code indicating whether its argument is positive, negative, or zero
7 Assuming the following definitions, which of the following functions puts in sequence of x’s in place of all occurrences of a given word in a given sequence of words?
HASKELL DEFINITION • rep n x = [ x | k <- [1 . . n]]
HASKELL DEFINITION • replaceWord badWord word
HASKELL DEFINITION • | badWord == word = rep (length badWord) ’x’
HASKELL DEFINITION • | otherwise = word
a censor badWord = map (replaceWord badWord)
b censor badWord = map . replaceWord badWord
c censor badWord = replaceWord badWord . map
d censor badWord = map badWord . replaceWord
=========================================================
答
案
在
下
面
=========================================================
1 c
在函数定义里还可以有分支,当满足某种条件时,用一种定义,当满足另外的条件时,用另外一套定义。有点像C语言中的switch语句。
f x | x > 0 = 1 | otherwise = -1
2 b
这道题容易做错。
先想想reverse ["able", "was", "I"]的结果是什么就不容易做错了。
以前提到过reverse函数的意思是把一个列表中的元素倒序排列, ["able", "was", "I"]这个里面有三个元素,倒过来就是[“I”, "was", "able"]。
那么map reverse函数的功能就可以这样描述了:把一个列表xsFather中的每个元素xsChild(本身还是一个列表)里的内容倒序。上例中xsFather就是["able", "was", "I"],第一个元素是xsChild就是“able”,倒过来就是"elba",这样map函数的意思也就清楚了,就是把reverse函数都作用于每个元素。
3 b
这里就是map函数的定义:
map f xs = [f x | x <- xs]
每一个参数f本身也是个函数,它要作用于后面xs里的每个元素x上,即f x。
第二个参数xs是一个列表,实际上就是把函数f遍历作用于xs中的元素上。
4 d
根据柯里函数的定义,g x也是一个函数,不妨记为h,那么
map (g x) ys = map h ys = [ h y | y <- ys]
这样应该好理解一些了。
对于柯里函数搞不懂的,需要认真学习高阶函数和不全函数等概念,一开始挺难理解的:-(
参见:《Two Dozen Short Lessons in Haskell》学习(九)- Types of Curried Forms and Higher Order Functions
5 b
就是一个回文序列的判断函数,如果是回文,就返回"yes",否则返回"no"
h xs | (xs == reverse xs) = "yes" -- 当一个序列如果等于它的反序时 | otherwise = "no"
加上括号就好理解一些了。
在haskell中这个竖线就叫guard,注意缩进。每一条竖线后面跟着一个布尔表达式,当它满足时就用=后面的定义,不满足时,继续判断下一个guard条件。
6 d
这个很简单,就是通常的求一个数的正负符号的函数。
7 a
rep n x = [ x | k <- [1 . . n]] 这个函数可以把x重复n次,这里的x并没有说是什么类型。
例如:rep 3 2 就等于[2,2,2]
rep 3 '2'就是['2', '2', '2'],即"222"
guard条件是: | badWord == word
紧接的定义是: = rep (length badWord) ’x’
就是把badWord全换为字符'x'
replaceWord "fuucck" "fuucck"就等于"xxxxxx"
这个函数可以用于去掉文章中不文雅的词。