3

Is there a way to compare them? This doesn't work for instance:

(equal? (flat-contract integer?) (flat-contract integer?))
Dale K
  • 25,246
  • 15
  • 42
  • 71
JRR
  • 6,014
  • 6
  • 39
  • 59
  • 1
    Possible duplicate of [How to test if two functions are the same?](https://stackoverflow.com/questions/33883671/how-to-test-if-two-functions-are-the-same) – Alexis King Jan 02 '19 at 01:49

2 Answers2

6

For certain kinds of contracts, you can use contract-equivalent?:

> (contract-equivalent? (flat-contract integer?) (flat-contract integer?))
#true
> (contract-equivalent? (and/c integer? positive?) (and/c integer? positive?))
#true
> (contract-equivalent? (or/c integer? string?) (or/c string? integer?))
#true

This returns #true when the contract system can prove that they are equivalent.

However, as the documentation notes, a #false result doesn't mean that they're not equivalent, it just means it doesn't know:

This function is conservative, so it may return #false when c1 does, in fact, accept the same set of values that c2 does.

> (contract-equivalent? integer? integer?)
#true
> (contract-equivalent? (lambda (x) (integer? x))
                        (lambda (x) (integer? x)))
#false
Sorawee Porncharoenwase
  • 6,305
  • 1
  • 14
  • 28
Alex Knauth
  • 8,133
  • 2
  • 16
  • 31
4
  1. First of all, note that the function flat-contract is for backward-compatibility, so you probably should not use it. From the documentation:

    This function is a holdover from before predicates could be used directly as flat contracts. It exists today for backwards compatibility.

  2. So your question is really to ask if two predicates are the same or not. In general this problem is undecidable due to the halting problem. However, for your purpose, you might be able to get away with referential equality.

    > ;; both are in the same memory address
      (eq? integer? integer?) 
    #t
    > ;; obviously not in the same memory address
      (eq? integer? real?)
    #f
    

    Please note its caveat

    > ;; although they look the same syntactically, 
      ;; the function objects are in different memory address
      (eq? (lambda (x) x) (lambda (x) x))
    #f
    > (define x (lambda (x) x))
    > (define y x)
    > ;; both are in the same memory address
      (eq? x y)
    #t
    > ;; flat-contract creates a function in a new memory address
      (eq? (flat-contract integer?) (flat-contract integer?))
    #f
    
Sorawee Porncharoenwase
  • 6,305
  • 1
  • 14
  • 28