[racket] A type that can't be converted to a contract

From: Neil Toronto (neil.toronto at gmail.com)
Date: Sat Nov 17 15:18:15 EST 2012

On 11/17/2012 12:18 PM, Jens Axel Søgaard wrote:
> I have the following contract on next-prime :
>
>      (: next-prime : (case-> (N -> N) (Z -> Z)) )
>
> It says that for all primes p, positive or negative, (next-prime p)
> will be an integer.
> Furthermore if p is a natural number, then (next-prime p) will also be
> a natural number.
>
> This type can't be converted to a contract:
>     Type Checker: The type of next-prime cannot be converted to a
> contract in: (next-prime 4)
>
> My understanding is that a since N is a subset of Z a predicate can't
> determine whether
> which case to use. Is there an alternative construct, that I can use
> in order to get
> a contract?

Vincent and I worked this out at the hackathon. There's now a very 
general but currently undocumented solution.

Most of the special functions have types that can't be converted to 
contracts. For example, the gamma function has the type

   (: gamma (case-> (One -> One)
                    (Integer -> Positive-Integer)
                    (Flonum -> Flonum)
                    (Real -> (U Positive-Integer Flonum))))

This could in principle be converted, but there are higher-order 
`case->' types in the math library that couldn't without running some 
serious theorem-proving. There probably always will be types that can't 
be converted to contracts, such types for functions that accept 
predicates (e.g. (Any -> Boolean : Real)).

I swear I will document this soon (it's on my TODO list!), but here's 
the general solution:

   (require typed/untyped-utils)

   (require/untyped-contract
    "private/functions/gamma.rkt"
    [gamma  (Real -> Real)])

   (provide gamma)

A Typed Racket module that imports `math/special-functions' will see 
gamma's original type, but its contract for untyped code is converted 
from the stated type (Real -> Real).

This should work for any type that TR can prove is a subtype of the 
original. Currently, `require/untyped-contract' can only be used in 
untyped Racket.

FWIW, this solution is only possible now that Racket has submodules.

The best place to use this is in "math/number-theory.rkt"... which I see 
is already using it for factorial and friends. You're all set.

Neil ⊥


Posted on the users mailing list.