
I’m trying to use the Gregor library in a Typed Racket project, but I can’t figure out the correct syntax for typing it. A minimalistic untyped file for printing the current date could look like this:
#lang racket
(require gregor)
(displayln (~t (today) "yyyy-MM-dd"))
This displays “2019–02–05” as expected. A crude attempt to convert this to typed Racket is this:
#lang typed/racket
(require/typed gregor
[~t (Any String -> String)]
[today (-> Any)]
)
(displayln (~t (today) "yyyy-MM-dd"))
But this gives the following error message:
~t: contract violation
any-wrap/c: Unable to protect opaque value passed as `Any`
value: #<date 2019-02-05>
in: the 1st argument of
(-> Any any/c String)
contract from: (interface for ~t)
I can’t find any explanation of what this means. I’ve also tried a few other variations on this, but to no avail.
What I think I need is to define the date
struct within the Gregor library (as per https://docs.racket-lang.org/ts-guide/typed-untyped-interaction.html), but the docs don’t explain how to do that. Does anyone know what I need to do here?

There are two strategies I know of (that are type-safe by default)

- Use an
#:opaque
type declaration in therequire/typed
form

- Use a
#:struct
declaration in therequire/typed
form

(1) can look like this: #lang typed/racket
(require/typed gregor
[#:opaque Date date?]
[~t (Date String -> String)]
[today (-> Date)])
(displayln (~t (today) "yyyy-MM-dd"))

(2) only works when the library exposes the struct to you, which gregor
doesn’t

Sweet. Got it working. Thanks a lot!

@xarxziux On a related note: I often regret making the time zone argument to today
(and other functions) optional. I think programmers routinely forget that “today” is an indexical term.

Google is currently making an effort internally to fix all date and time bugs in all Java code and so far the biggest cause of them is implicitly relying on the system default clock and time zone

@tim has joined the channel

It sneaks global mutable state into places, and if that’s not bad enough the state has confusing and unintuitive semantics

It certainly does

Interestingly the other main problem is APIs and libraries that don’t support nanosecond precision

That is interesting. I haven’t written Java in a long time, but, while I wasn’t especially surprised to see that java.util.Date
only has millisecond precision, I was surprised that Joda was the same. The newer java.time
stuff has nanosecond precision, I believe (as Gregor does).

Running the following program raises a use-before-initialization error for make-foo/c
when evaluating the (invoke-unit foo@)
. I suspect this is a bug (maybe related to https://github.com/racket/racket/issues/1652), but does anyone know if it is supposed to work, or if there’s some other way to achieve this? #lang racket
(define-signature foo^
[foo?
(define-values-for-export [make-foo/c] (-> foo?))
make-foo/c
(contracted [make-foo make-foo/c])])
(define-unit foo@
(import)
(export foo^)
(define (foo? x)
(eq? x 'foo))
(define (make-foo)
'foo))
(invoke-unit foo@)

Yup. Migrating code to jave.time
is a big part of the bug fix effort.

I’ve opened https://github.com/racket/racket/issues/2459 to track this.

I only need it to parse invoice dates pulled from a CSV file and get the difference between them. I doubt it’ll be an issue. Your library works just fine for me. :+1: