cur/cur-doc/cur/scribblings/stdlib/sugar.scrbl
2016-01-19 11:07:57 -05:00

202 lines
6.1 KiB
Racket

#lang scribble/manual
@(require
"../defs.rkt"
scribble/eval)
@(define curnel-eval (curnel-sandbox "(require cur/stdlib/nat cur/stdlib/bool cur/stdlib/sugar cur/stdlib/list)"))
@title{Sugar}
The @tech{curnel forms} are sort of terrible for actually writing code. Functions and applications are
limited to single artity. Functions type must be specified using the dependent @racket[forall], even
when the dependency is not used. Inductive elimination can only be done via the primitive eliminator
and not via pattern matching. However, with the full force of Racket's syntactic extension system, we
can define not only simply notation, but redefine what application means, or define a pattern matcher
that expands into the eliminator.
@defmodule[cur/stdlib/sugar]
This library defines various syntactic extensions making Cur easier to write than writing raw TT.
@defform*[((-> decl decl ... type)
( decl decl ... type)
(forall decl decl ... type)
( decl decl ... type))
#:grammar
[(decl
type
(code:line (identifier : type)))]]{
A multi-artiy function type that supports dependent and non-dependent type declarations and automatic currying.
@examples[#:eval curnel-eval
(data And : (-> Type Type Type)
(conj : (-> (A : Type) (B : Type) A B ((And A) B))))
((((conj Bool) Bool) true) false)]
@examples[#:eval curnel-eval
(data And : (forall Type Type Type)
(conj : (forall (A : Type) (B : Type) A B (And A B))))
((((conj Bool) Bool) true) false)]
}
@defform*[((lambda (a : t) ... body)
(λ (a : t) ... body))]{
Defines a multi-arity procedure that supports automatic currying.
@examples[#:eval curnel-eval
((lambda (x : Bool) (lambda (y : Bool) y)) true)
((lambda (x : Bool) (y : Bool) y) true)
]
}
@defform[(#%app f a ...)]{
Defines multi-arity procedure application via automatic currying.
@examples[#:eval curnel-eval
(data And : (-> Type Type Type)
(conj : (-> (A : Type) (B : Type) A B ((And A) B))))
(conj Bool Bool true false)]
}
@defform*[((define name body)
(define (name (x : t) ...) body))]{
Like the @racket[define] provided by @racketmodname[cur], but supports
defining curried functions via @racket[lambda].
}
@defform[(elim type motive-result-type e ...)]{
Like the @racket[elim] provided by @racketmodname[cur], but supports
automatically curries the remaining arguments @racket[e ...].
@examples[#:eval curnel-eval
(elim Bool Type (lambda (x : Bool) Bool)
false
true
true)]
}
@defform*[((define-type name type)
(define-type (name (a : t) ...) body))]{
Like @racket[define], but uses @racket[forall] instead of @racket[lambda].
}
@defform[(match e [maybe-in] [maybe-return] [pattern body] ...)
#:grammar
[(maybe-in
(code:line #:in type))
(maybe-return
(code:line #:return type))
(pattern
constructor
(code:line (constructor (x : t) ...)))]]{
A pattern-matcher-like syntax for inductive elimination.
Does not actually do pattern matching; instead, relies on the
constructors patterns being specified in the same order as when the
inductive type was defined.
Inside the @racket[body], @racket[recur] can be used to refer to the
inductive hypotheses for an inductive argument.
Generates a call to the inductive eliminator for @racket[e].
Currently does not work on inductive type-families as types indices
are not inferred.
If @racket[#:in] is not specified, attempts to infer the type of @racket[e].
If @racket[#:return] is not specified, attempts to infer the return type of the @racket[match].
@examples[#:eval curnel-eval
(match z
[z true]
[(s (n : Nat))
false])]
@examples[#:eval curnel-eval
(match (s z)
#:in Nat
#:return Bool
[z true]
[(s (n : Nat))
(not (recur n))])]
@examples[#:eval curnel-eval
((match (nil Bool)
[(nil (A : Type))
(lambda (n : Nat)
(none A))]
[(cons (A : Type) (a : A) (rest : (List A)))
(lambda (n : Nat)
(match n
[z (some A a)]
[(s (n-1 : Nat))
((recur rest) n-1)]))])
z)]
}
@defform[(recur id)]{
A form valid only in the body of a @racket[match] clause.
Generates a reference to the induction hypothesis for @racket[x]
inferred by a @racket[match] clause.
}
@defform[(let (clause ...) body)
#:grammar
[(clause
(code:line (id expr))
(code:line ((id : type) expr)))]]{
Evaluates the expressions @racket[expr] from each clause, left to right, and binds them to each
@racket[id]. If a @racket[type] is not given for the @racket[id], attempts to infer the type of the
corresponding @racket[expr], raising a syntax error if no type can be inferred.
@examples[#:eval curnel-eval
(let ([x Type]
[y (λ (x : (Type 1)) x)])
(y x))
(let ([x uninferrable-expr]
[y (λ (x : (Type 1)) x)])
(y x))]
}
@defform[(:: e type)]{
Check that expression @racket[e] has type @racket[type], causing a type-error if not, and producing
@racket[(void)] if so.
@examples[#:eval curnel-eval
(:: z Nat)
(:: true Nat)]
}
@defform[(run syn)]{
Like @racket[normalize/syn], but is a syntactic form to be used in surface syntax.
Allows a Cur term to be written by computing part of the term from
another Cur term.
@examples[#:eval curnel-eval
(lambda (x : (run (if true Bool Nat))) x)]
}
@defform[(step syn)]{
Like @racket[run], but uses @racket[step/syn] to evaluate only one step and prints intermediate
results before returning the result of evaluation.
@examples[#:eval curnel-eval
(step (plus z z))]
}
@defform[(step-n natural syn)]{
Like @racket[step], but expands to @racket[natural] calls to @racket[step].
@examples[#:eval curnel-eval
(step-n 3 (plus z z))]
}
@defform[(query-type expr)]{
Print the type of @racket[expr], at compile-time. Similar to Coq's @racketfont{Check}.
@examples[#:eval curnel-eval
(query-type Bool)]
}