3

Suppose I define a struct for a set with its "center".

(struct centered-set (center elems))

I want to guarantee the following conditions.

  • elems is a set.
  • center is an member of elems.

I can express the conditions with #:guard. Is there a way to express the same conditions as a contract?

For functions, ->i works as a combinator for that kind of dependent contracts. How to express dependent contracts for structs?

sazf
  • 33
  • 3
  • 1
    Take a look at [struct/dc](https://docs.racket-lang.org/reference/data-structure-contracts.html#%28form._%28%28lib._racket%2Fcontract%2Fprivate%2Fstruct-dc..rkt%29._struct%2Fdc%29%29) – Sorawee Porncharoenwase May 22 '20 at 09:24
  • @SoraweePorncharoenwase Thank you. As far as I can see, `struct/dc` is for a contract that _accepts struct instances_. I want to impose contracts _on structs_, like `(contract-out [struct ...])`. – sazf May 22 '20 at 09:42

1 Answers1

2

IIUC, contract-out doesn't support anything like that. However, you can simulate the functionality by providing the constructor and accessors manually with the contract attached:

#lang racket

(module foo racket
  (provide (contract-out [bt (-> any/c any/c any/c (bst/c 1 10))]
                         [bt-val (-> (bst/c 1 10) any/c)]
                         [bt-left (-> (bst/c 1 10) any/c)]
                         [bt-right (-> (bst/c 1 10) any/c)]))

  (define (bst/c lo hi)
    (or/c #f
          (struct/dc bt
                     [val (between/c lo hi)]
                     [left (val) #:lazy (bst/c lo val)]
                     [right (val) #:lazy (bst/c val hi)])))

  (struct bt (val left right)))

(require 'foo)

(bt 11 #f #f)

It should be possible to write a provide transformer to automate this process.

Sorawee Porncharoenwase
  • 6,305
  • 1
  • 14
  • 28