首页 > 解决方案 > 合约:如何接受任何匹配签名的功能?

问题描述

我正在尝试编写此合同:“接受一个至少接受一个参数并返回布尔值的函数。”

关键是我只关心它返回一个布尔值,并且它接受一个或多个参数——例如,它可以是一个接受单个参数的函数,或者一个接受两个参数的函数,并且应该接受其中任何一个。

这是我尝试过的:

第一次尝试

(-> any/c any/c ... boolean?)

第二次尝试

(->* (any/c)
     (any/c ...) ; => syntax error
     boolean?)

第三次尝试

(->* (any/c)
     #:rest (listof any/c)
     boolean?)

在每一种情况下,合同似乎都期望参数不仅包含在合同规范中,而且要完全匹配。也就是说,例如,它必须是一个接受任意多个参数的函数,而不是“如果它是一个接受 2 个参数的函数,那很好,因为我正在接受接受任意数量参数的函数”。

怎么写这样的合同?

标签: racketdatacontractcontract

解决方案


这行得通吗?

(define/contract (f x)
  (and/c (unconstrained-domain-> boolean?)
         (lambda (p)
           (let loop ([n (procedure-arity p)])
             (match n
               [(? number? n) (>= n 1)]
               [(arity-at-least n) (>= n 1)]
               [(list xs ...) (ormap loop xs)]))))
  #t)

推荐阅读