Search code examples
functional-programmingschemelispracket

Racket parametric contracts errors


I've started learning contracts and I have such procedure:

(define/contract (foldr-map f a xs)
  foldr-map/c
  (define (it a xs ys)
    (if (null? xs)
        (cons ys a)
        (let* [(p (it a (cdr xs) ys))
              (fc (f (car xs) (cdr p)))]
          (cons (cons (car fc) (car p)) (cdr fc)))))

  (it a xs null))

(foldr-map (lambda (x a) (cons a (+ a x))) 0 `(1 2 3))

And I have flodr-map/c contract defined as:


(define foldr-map/c
  (parametric->/c [x a] (->
                         (-> x a (cons/c a number?))
                         a
                         (listof x)
                         (cons/c (listof a) a))))

But I see such error:

foldr-map: broke its own contract
  promised: a
  produced: 3
  in: the 2nd argument of
      the 1st argument of
      (parametric->/c
       (x a)
       (->
        (-> x a (cons/c a number?))
        a
        (listof x)
        (cons/c (listof a) a)))
  contract from: (function foldr-map)
  blaming: (function foldr-map)
   (assuming the contract is correct)

I know that the procedure works correctly so the contract has to be wrong. The procedure takes the argument f which is a function.

The contract has 2 parameters:

  • x is an element of list xs
  • a is an accummulator

When I change the contract to be:

(define foldr-map/c
  (parametric->/c [x a] (->
                         (-> x number? (cons/c number? number?))
                         a
                         (listof x)
                         (cons/c (listof a) a))))

I get such error:

foldr-map: broke its own contract
  promised: number?
  produced: #<a>
  in: the 2nd argument of
      the 1st argument of
      (parametric->/c
       (x a)
       (->
        (-> x number? (cons/c number? number?))
        a
        (listof x)
        (cons/c (listof a) a)))
  contract from: (function foldr-map)
  blaming: (function foldr-map)
   (assuming the contract is correct)

So at this point I got lost.


Solution

  • I found a solution:

    (define foldr-map/c
      (parametric->/c [x a] (->
                             (-> x a (cons/c a a))
                             a
                             (listof x)
                             (cons/c (listof a) a))))
    

    It makes sense and seems kinda obvious but it took quite some debugging time to figure it out.