Compact Annotations
:  :
6.12

Compact Annotations

Jack Firth <[email protected]>

 (require compact-annotations)
  package: compact-annotations

This library provides a more convenient syntax for writing typed racket polymorphic and curried functions. It is very similar to Haskell type annotations.

source code: https://github.com/jackfirth/compact-annotations

syntax

(:: id maybe-polymorphic function-type)

 
maybe-polymorphic = 
  | type-var-id ... =>
     
function-type = arg-type ... maybe-opt maybe-rest -> function-type
  | arg-type ... maybe-opt maybe rest -> result-type
     
maybe-opt = 
  | + arg-type ...
     
maybe-rest = 
  | * arg-type
Declares that id has the type determined by function-type, which may be a parametric type over type-var-id ... if provided. The syntax of function-type allows for partially applied function types, optional argument types, and rest argument types.

With this syntax, the type of the identity function can be defined as follows:

Examples:
> (:: ident A => A -> A)
> (define (ident a) a)
> (:print-type ident)

(All (A) (-> A A))

> (ident 10)

- : Integer [more precisely: Positive-Byte]

10

A function that takes one value and returns a function that takes another value and ignores it, returning the first value can have it’s type defined as follows:

Examples:
> (:: first-value A B => A -> B -> A)
> (define ((first-value a) b) a)
> (:print-type first-value)

(All (A) (-> A (All (B) (-> B A))))

> ((first-value 'foo) 20)

- : Symbol [more precisely: 'foo]

'foo

Optional arguments can have their type specified with a +. For example, a function that greets people with "Hello" by default can have it’s type defined as follows:

Examples:
> (:: greet String + String -> String)
> (define (greet name [greeting "Hello"])
    (string-append greeting " " name))
> (:print-type greet)

(->* (String) (String) String)

> (greet "John")

- : String

"Hello John"

> (greet "Jack" "Hey")

- : String

"Hey Jack"

Rest arguments can also have their type specified with a *. A function that converts it’s arguments from one type to String then appends them all can have its type specified as follows:

Examples:
> (:: append-as-string A => (A -> String) * A -> String)
> (define (append-as-string a->string . as)
    (apply string-append (map a->string as)))
> (:print-type append-as-string)

(All (A) (-> (-> A String) A * String))

> (append-as-string number->string 1 2 3 4 5)

- : String

"12345"