我实施 "map" 时违反合同

contract violation in my implementation of "map"

我是从 Scheme 开始的(实际上是 Racket 和 DrRacket),我想通过实现一个 map 函数来练习(将一个函数应用于列表的所有元素),但是有一些错误我不明白. (除了我的命令式背景,我还有 haskell 的基本知识)

我想翻译下面一段haskell(只是为了展示算法):

map f [] = []
map f x:xs = (f x) : (map f xs)

这是我的代码:

(define (map f xs)

  (if (= xs '()) '() ; if list is empty, return empty list
      (cons (f (car xs)) (map f (cdr xs))))

  )

为了测试它,我使用了这个:

(define (testFunction x) (+ x 1))
(define testList '(1 2 3 4 5))
(map testFunction testList)

我收到以下错误:

=: contract violation
expected: number ?
given : '(1 2 3 4 5)
argument position: 1st
other arguments...:

其中高亮谓词(=xs'())

有什么建议吗?

如果您使用的是 DrRacket,那么对于这种情况,只需使用 (empty?):

(if (empty? xs)
    xs ; because xs is empty
    ...)

= function is specifically for equality between numbers. It has special handling for numeric values by handling comparisons between exact and inexact numbers. In general, though, for non-numeric equality, you should use the equal? 谓词:

> (equal? '() '())
#t

在这种特殊情况下,如 Raghav, you can also use empty? or null? to test for the empty list (the empty? predicate is just an alias for null? 所述)。

哇 - 其他一些人已经抢在我前面了,但无论如何我都会分享我的答案。

您的问题源于您使用 = 来测试列表是否为空。

来自 the docs 中的 =

Returns #t if all of the arguments are numerically equal, #f otherwise.

为了让您的程序正常运行,我建议使用 equal? 来测试两个列表是否相等,或者更好的是,使用 empty?null? 来测试是否xs 是一个空列表。 (我希望你不要生气,但我也将代码修改为(可以说)更惯用的 Scheme)。

(define (mymap f xs)
  (if (empty? xs)
    xs
    (cons 
      (f (car xs))
      (mymap f (cdr xs)))))

(define (test-function x) (+ x 1))
(define test-list (list 1 2 3 4))

(mymap test-function test-list)