# Exporting a struct invariant contract

**URL:** <https://racket.discourse.group/t/exporting-a-struct-invariant-contract/3694>\
**Category:** Questions & Answers\
**Tags:** question, contract, struct\
**Created:** [April 17, 2025, 4:35pm UTC](https://racket.discourse.group/t/exporting-a-struct-invariant-contract/3694 "2025-04-17T16:35:07Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![KevinW](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/kevinw/32/2292_2.png) [@KevinW](https://racket.discourse.group/u/KevinW)\
**Post date:** [April 17, 2025, 4:35pm UTC](https://racket.discourse.group/t/exporting-a-struct-invariant-contract/3694/1 "2025-04-17T16:35:07Z")

</div>

Hi,

I'm trying to create a struct with a contract that involves a relationship between two fields. The struct needs to be exported. It seems like what I need is an "invariant contract" as in `struct/dc`: [8.1&nbsp;Data-structure Contracts](https://docs.racket-lang.org/reference/data-structure-contracts.html#%28form._%28%28lib._racket%2Fcontract%2Fprivate%2Fstruct-dc..rkt%29._struct%2Fdc%29%29)

However I don't see how to export a struct using a contract created through `struct/dc`. The examples of exporting structs use `contract-out` and its `struct` form. But that only allows for structs to have per-field contracts, not a multi-field invariant contract.

Does anyone know how to create and export a struct with a contract that involves multiple fields?

Thanks

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [April 17, 2025, 9:58pm UTC](https://racket.discourse.group/t/exporting-a-struct-invariant-contract/3694/2 "2025-04-17T21:58:45Z")

</div>

AFAICT, the contract you get from `struct/dc` is like a stronger version of the `instance?` predicate you get from the `struct` form. So you can use it in other contract combinators (like the argument or result positions of `->`), and as the contract for a value `[my-instance my-struct/dc-contract]`.

If you wanted to contract the fields and constructor, it's probably a little more boilerplate.

Something like

```racket
(provide
(contract-out
[instance-field1 (-> my-dc-contract field1-contract)] …
[instance (-> … field contract … my-dc-contract)]))

```

And of course that means you can't use `instance` in `match` and `struct-copy` for all the usual reasons. I'll let someone else post the workaround for that?

---

<div class="post-metadata">

**Author:** ![KevinW](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/kevinw/32/2292_2.png) [@KevinW](https://racket.discourse.group/u/KevinW)\
**Post date:** [April 18, 2025, 10:23pm UTC](https://racket.discourse.group/t/exporting-a-struct-invariant-contract/3694/3 "2025-04-18T22:23:45Z")

</div>

Thanks, this makes sense. Yes I see that I can create a `instance/c` contract with `struct/dc`, export that, write separate contracts for the constructor and each other procedure, and involve the `instance/c` in those procedures' contracts. It's a little tedious but works.

It would be nice to be able to export the `instance` structure type, so that, like you said, features like `match` can work in other modules. I'm eager to hear if anyone knows how to do that.
