3.2 Sugar
The 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 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.
(require cur/stdlib/sugar) | package: cur-lib |
Changed in version 0.20 of package cur-lib: Moved Type synonym from Curnel.
> (data And : 2 (-> Type Type Type) (conj : (-> (A : Type) (B : Type) A B ((And A) B)))) eval:1:0: ->: expected one of these literal symbols: `Π',
`Pi', `∀', or `forall'
at: ->
in: (-> Type Type Type)
> ((((conj Bool) Bool) true) false) conj: unbound identifier in module
> (data And : 2 (forall Type Type Type) (conj : (forall (A : Type) (B : Type) A B (And A B)))) eval:3:0: forall: bad syntax
in: (forall Type Type Type)
> ((((conj Bool) Bool) true) false) conj: unbound identifier in module
> ((lambda (x : Bool) (lambda (y : Bool) y)) true) #<procedure>
> ((lambda (x : Bool) (y : Bool) y) true) #<procedure>
> (data And : 2 (-> Type Type Type) (conj : (-> (A : Type) (B : Type) A B ((And A) B)))) eval:7:0: ->: expected one of these literal symbols: `Π',
`Pi', `∀', or `forall'
at: ->
in: (-> Type Type Type)
> (conj Bool Bool true false) conj: unbound identifier in module
> (: id (forall (A : Type) (a : A) A)) :: unbound identifier in module
> (define (id A a) a) <pkgs>/cur-lib/cur/curnel/coc-saccharata.rkt:107:17: λ: no
expected type, add annotations
at: (λ A (λ/c- a a))
in: (λ A (λ/c- a a))
parsing context:
while parsing has-expected-type
term: (λ A (λ/c- a a))
location:
<pkgs>/cur-lib/cur/curnel/coc-saccharata.rkt:107:17
syntax
(match e [maybe-in] [maybe-return] [pattern body] ...)
maybe-in = #:in type maybe-return = #:return type pattern = constructor | (constructor x ...) | (constructor (x : t) ...)
Pattern variables do not need to be annotated, as the ‘match‘ form can infer their types. If pattern variables are annotated, then the ‘match‘ form will ensure the annotation matches the expected type before elaborating.
If ‘match‘ is used under a ‘define‘, ‘match‘ can be used to define simple primitive recursive functions, defined by induction on their first argument.
Inside the body, recur can be used to refer to the inductive hypotheses for an inductive argument. Generates a call to the inductive eliminator for e. Currently does not work on inductive type-families as types indices are not inferred.
If #:in is not specified, attempts to infer the type of e. If #:return is not specified, attempts to infer the return type of the match.
> (match z [z true] [(s (n : Nat)) false]) eval:11:0: match: expected one of these literals: #:return,
#:in, #:as, or #:with-indices
at: (z true)
in: (match z (z true) ((s (n : Nat)) false))
> (match z [(s n) false] [z true]) eval:12:0: match: expected one of these literals: #:return,
#:in, #:as, or #:with-indices
at: ((s n) false)
in: (match z ((s n) false) (z true))
> (match (s z) #:in Nat #:return Bool [z true] [(s n) (not (recur n))]) recur: unbound identifier in module
> (define (+ (n : Nat) (m : Nat)) (match n [z m] [(s n) (s (+ n m))])) eval:14:0: match: expected one of these literals: #:return,
#:in, #:as, or #:with-indices
at: (z m)
in: (match n (z m) ((s n) (s (+ n m))))
> ((match (nil Bool) [nil (lambda (n : Nat) (none A))] [(cons (a : Bool) (rest : (List Bool))) (lambda (n : Nat) (match n [z (some Bool a)] [(s (n-1 : Nat)) ((recur rest) n-1)]))]) z) eval:15:0: match: expected one of these literals: #:return,
#:in, #:as, or #:with-indices
at: (nil (lambda (n : Nat) (none A)))
in: (match (nil Bool) (nil (lambda (n : Nat) (none A)))
((cons (a : Bool) (rest : (List Bool))) (lambda (n : Nat)
(match n (z (some Bool a)) ((s (n-1 : Nat)) ((recur rest)
n-1))))))
syntax
(let (clause ...) body)
clause = (id expr) | ((id : type) expr)
> (let ([x Type] [y (λ (x : (Type 1)) x)]) (y x)) (Type- 0)
> (let ([x uninferrable-expr] [y (λ (x : (Type 1)) x)]) (y x)) uninferrable-expr: unbound identifier in module
Changed in version 0.20 of package cur-lib: Broken by new Curnel; fix is part of planned rewrite of evaluator.
Changed in version 0.20 of package cur-lib: Broken by new Curnel; fix is part of planned rewrite of evaluator.
> (query-type Bool) query-type: unbound identifier in module