Types 如何在Scheme中定义类型谓词
“普通”函数通常仅在给定类型的对象域上定义,但某些函数,如Scheme类型谓词Types 如何在Scheme中定义类型谓词,types,scheme,racket,predicate,Types,Scheme,Racket,Predicate,“普通”函数通常仅在给定类型的对象域上定义,但某些函数,如Scheme类型谓词list?或procedure?,是为任何类型的参数定义的,甚至可以应用于自身。因此,例如(列表?程序?计算为#f,(程序?程序?计算为#t。我试图弄清楚如何编写这种完全定义的函数,但还没有找到讨论这个问题的源代码 例如,假设我们使用以下构造函数和选择器实现了练习2.4中描述的成对数据类型: (define (cons x y) (lambda (m) (m x y))) (define
list?
或procedure?
,是为任何类型的参数定义的,甚至可以应用于自身。因此,例如(列表?程序?
计算为#f
,(程序?程序?
计算为#t
。我试图弄清楚如何编写这种完全定义的函数,但还没有找到讨论这个问题的源代码
例如,假设我们使用以下构造函数和选择器实现了练习2.4中描述的成对数据类型:
(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) p)))
(define (cdr z)
(z (lambda (p q) q)))
然后,我将如何定义一个谓词
对?
,它为使用cons
构造的任何对象返回#t
,并为未使用#f
构造的对象返回#t
?更一般地说,像list?
和procedure?
这样的类型谓词是如何实现的?您不能用显示的代码实现的。程序不透明
作为一种可能性,您必须更改构造函数/访问器以使用标记列表
(define *church-pair-tag* (list '*church-pair-tag*))
(define (cons x y)
(cons *church-pair-tag* (lambda(m) (m x y))))
(define (church-pair? x)
(and (pair? x)
(eq? *church-pair-tag* (car x))
(procedure? (cdr x))))
....
但这显然不是万无一失的
谓词
pair?
和procedure?
是内置的,可能是通过某种幕后魔术实现的<代码>列表?可以根据配对?
、空?、汽车
和cdr
实现,这很容易。重新定义过程,使第一个参数为您正在创建的对象类型:
(define +type-pair+ 'pair)
(define +type-number+ 'number)
(define (cons a d)
(lambda (m) (m +type-pair+ a d)))
(define (type x)
(x (lambda (t . rest) t)))
(define (pair? c)
(eq? (type c) +type-pair+))
(define (car c)
(if (pair? c)
(c (lambda (t a d) a))
(error "Argument is not pair!")))
(define (cdr c)
(if (pair? c)
(c (lambda (t a d) d))
(error "Argument is not pair!")))
(define (number? c)
(if (type c) +type-number+))
您可以使用它来定义语言中的所有内容,甚至是过程,但是所有的过程都必须支持使用(type x)给出它的类型,并且所有使用某物的过程都必须确保类型正确。将成对实现为闭包可能是最慢的方法,所以这只是一个SICP思维实验,让您了解闭包是什么。Arc对所有数据类型使用标记,但将数据保留为数据。您应该看看Arc,看看标记是如何成为一种方式的。顺便说一句,在Racket中,用生成的结构谓词已经为您完成了这项工作,因此您不必手动实现它
每个专业级别的方案都通过结构或记录提供类似的功能。请参阅,其中描述了许多其他方案实现将为您提供的功能。您为什么会关心这对方案是如何构建的?如果它是一对,那么不管怎样它都是一对。您可以将
pair?
定义为一个不为null的列表,其cdr不为null,但cdr上的递归为#f
。我很确定list?
谓词需要是一个内置函数,因为它太基本了。@d11wtq(定义(list?x)(和(pair?x)(或(null?(cdr x)))(list?(cdr x』)
检查参数对象是否是一个有限的正确列表<代码>配对?仅检查它是否为cons单元格数据对象<代码>(let((a(列表1)))(set cdr!a)(pair?(cdr a)))必须能够返回#t
。您的第二行有一个输入错误。谢谢,但我对如何“手动”操作非常感兴趣,只是为了了解本机提供的功能的“隐藏”机制。