用高阶函数做抽象

高阶函数是至少满足下列一个条件的函数:

  • 接受一个或多个函数作为输入
  • 输出一个函数

在数学中它们也叫做算子(运算符)或泛函。微积分中的导数就是常见的例子,因为它映射一个函数到另一个函数。

在无类型lambda演算,所有函数都是高阶的;在有类型lambda演算(大多数函数式编程语言都从中演化而来)中,高阶函数一般是那些函数型别包含多于一个箭头的函数。在函数式编程中,返回另一个函数的高阶函数被称为Curry化的函数。

在很多函数式编程语言中能找到的map函数是高阶函数的一个例子。它接受一个函数f作为参数,并返回接受一个列表并应用f到它的每个元素的一个函数。

抽象出求和函数

(define (sum f a b next)
  (if (> a b) 0
      (+ (f a)
         (sum f (next a) b next))))
(define (identity x) x)
(define (square x) (* x x))
(define (inc x) (+ x 1))

// 求a到b的和
(define (sum-int a b)
  (sum identity a b inc))

// 求a到b的平方和
(define (sum-squ a b)
  (sum square a b inc))

(sum-int 1 10)
(sum-squ 1 4)
// 输出
55
30

同理,可抽象出求乘积过程

// 递归
(define (product f a b next)
  (if (> a b) 1
      (* (f a)
         (product f (next a) b next))))

// 迭代
(define (pro f a b next)
  (define (iter a result)
    (if (> a b) result
        (* (f a)
           (iter (next a) result))))
  (iter a 1))
// 求a到b的积
(define (product-int a b)
  (product identity a b inc))

(define (pro-int a b)
  (pro identity a b inc))

// 求n的阶乘
(define (factorial n)
  (product identity 1 n inc))

(product-int 1 5)
(pro-int 1 5)
(factorial 6)
// 输出
120
120
720

由以上的求和、求乘积可知这两种过程有共同点,于是可再抽象成累积过程,再利用累积过程实现求和、求乘积函数

(define (ac comb null-val f a next b)
  (define (iter a result)
    (if (> a b) result
        (iter (next a)
              (comb (f a) result))))             
  (iter a null-val))
(define (sum-ac a b)
  (ac + 0 identity a inc b))

(define (pro-ac a b)
  (ac * 1 identity a inc b))

(sum-ac 1 10)
(pro-ac 1 6)
// 输出
55
720

引进一个处理被组合项的过滤器(filter)概念。
在计算过程中,只组合起由给定范围得到的项里的那些满足特定条件的项。

// 递归
(define (acc comb null-val f a b next filter)
   (if (> a b) null-val
       (let ((rest-terms (acc comb null-val f (next a) b next filter)))
         (if (filter a) (comb (f a) rest-terms)
             rest-terms))))

// 迭代
(define (accu comb null-val f a b next filter)
  (define (iter a result)
    (if (> a b) result
        (let ((rest-terms (iter (next a) result)))
          (if (filter a) (comb (f a) rest-terms)
              rest-terms))))
  (iter a null-val))
(require math)

// 求从a到b的素数之和
(define (prime-sum a b)
  (accu + 0 identity a b inc prime?))

// 求小于n的所有与n互素的正整数之乘积
(define (coprime-pro n)
  (accu * 1 identity 1 n inc (lambda (x) (coprime? x n))))

(prime-sum 1 10)
(coprime-pro 10)
// 输出
17
189

构造f的n次重复应用,将其定义为一个函数,这个函数在x的值是f(f(...(f(x))...))

(define (compose f g)
  (lambda (x) (f (g x))))

(define (repeated f n)
  (if (= n 1) f
      (compose f
               (repeated f (- n 1)))))
((repeated square 2) 5)    ; (square (square 5))
((repeated square 3) 2)    ; (square (square (square 2)))

// 输出
625
256
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容