Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Types 如何在Scheme中定义类型谓词_Types_Scheme_Racket_Predicate - Fatal编程技术网

Types 如何在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

“普通”函数通常仅在给定类型的对象域上定义,但某些函数,如Scheme类型谓词
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
。您的第二行有一个输入错误。谢谢,但我对如何“手动”操作非常感兴趣,只是为了了解本机提供的功能的“隐藏”机制。