Hi,
On 2/14/22 17:32, Ricardo Wurmus wrote:
As you can probably tell easily by looking at this message, the
“service” field of the operating system configuration looked something
like this:
(services (append (list a b c %desktop-services) #;oops))
instead of this
(services (append (list a b c) %desktop-services))
This is because INSTANTIATE-MISSING-SERVICES — and FOLD-SERVICES, and
many more — assumes that it is only passed a plain list of services. It
then proceeds to call SERVICE-KIND on what may or may not be a service.
I think we should add simple type checks, something like this:
(define (listof pred)
(lambda (thing)
(and (list? thing) (every pred thing))))
…
(define (assert-type type-check thing message)
(or (false-if-exception (type-check thing))
(report-error (G_ "type error: …\n" message))))
;; Use ASSERT-TYPE in an example procedure.
(define (do-something-with-services services)
(assert-type (listof service?) services
"SERVICES must be a list of <service> values.")
;; Do things…
(map service-kind services))
What do you think? There are many different ways of implementing this
(a new variant of DEFINE that also accepts a type declaration, an assert
like above, a fancier assert that composes a helpful error message by
itself, a separate type declaration that is looked up only when the
corresponding procedure is called in a certain context, etc), but I’d
first like to know if there is consensus that we want something like
this.
As a Guix user and contributor, I would love better error messages.
As a Racketeer, I think you're half way to reinventing contracts.
In particular, since the operating system services field is thunked,
this example already points to the desirability of higher-order contracts.
Using "contracts" need not initially involve all the bells and whistles
of Racket's contract library. For example, higher-order contracts can be
implemented with `lambda` in the absence of special runtime support for
chaperones and impersonators, as illustrated in [1]. But the Racket
community has accumulated a great deal of both theoretical insight and
implementation experience in many subtle corners of this problem: I hope
Guix can build on that experience.
-Philip
[1]: https://docs.racket-lang.org/guide/Building_New_Contracts.html