Search code examples
racketcontract

Defining racket contracts with a custom predicate


I'm just starting to learn about contracts (via exercism.io) and so I have made a contract that is:

[step1 (-> (and/c number?
                  less-than-one-hundred?)
            string?)]

What I think I'm saying is the function will take a number less than one hundred (which is a function defined as:

(define (less-than-one-hundred? n)
  (< n 100))

But when I call the function like this:

(step1 100)

No contract violation. What am I doing wrong?


Solution

  • Here's a concrete example of what Soegaard's answer is saying:

    def-step1.rkt

    #lang racket
    
    (provide (contract-out
              [step1 (-> (and/c number?
                                less-than-one-hundred?)
                         string?)]))
    
    (define (less-than-one-hundred? n)
      (< n 100))
    
    (define (step1 x) "")
    

    use-step1.rkt

    #lang racket
    
    (require "def-step1.rkt")
    
    (step1 100)
    

    This produces a contract violation like you expect, and in particular, it blames use-step1.rkt, a different "contract party" than def-step1.rkt where the contract came from:

    step1: contract violation
      expected: less-than-one-hundred?
      given: 100
      in: an and/c case of
          the 1st argument of
          (->
           (and/c number? less-than-one-hundred?)
           string?)
      contract from: .../def-step1.rkt
      blaming: .../use-step1.rkt
       (assuming the contract is correct)