Skip to content

Instantly share code, notes, and snippets.

@dannypsnl
Last active September 20, 2022 18:10
Show Gist options
  • Save dannypsnl/98a048103eed186b9fd1aeca7f1386dc to your computer and use it in GitHub Desktop.
Save dannypsnl/98a048103eed186b9fd1aeca7f1386dc to your computer and use it in GitHub Desktop.
strictly positive checker
#lang racket
(require syntax/parse/define
(for-syntax syntax/stx))
(begin-for-syntax
(define-syntax-class type
#:datum-literals (->)
(pattern (~literal Type)
#:attr occurs (λ (D) #f))
(pattern x:id
#:attr occurs (λ (D)
(eq? (syntax->datum D)
(syntax->datum #'x))))
(pattern (t1:type -> t2:type)
#:attr occurs (λ (D)
(or ((attribute t1.occurs) D)
((attribute t2.occurs) D)))))
(define-syntax-class constructor
#:datum-literals (:)
(pattern (name:id : ty:type)
#:attr check-strictly-positive
(λ (D)
(syntax-parse #'ty
#:datum-literals (->)
; a type in Pi form
[(L:type -> R:type)
(syntax-parse #'L
[(L:type -> R:type)
(not ((attribute L.occurs) D))]
[else #t])]
; or we don't care
[_ #t])))))
(define-syntax-parser data
[(_ name:id : ty:type
c*:constructor ...)
(for-each (λ (check c)
(unless (check #'name)
(raise-syntax-error 'data-type
(format "~a is not strictly positive" (syntax->datum #'name))
c)))
(attribute c*.check-strictly-positive)
(syntax->list #'(c* ...)))
#'(void)])
(data Nat : Type
[z : Nat]
[s : (Nat -> Nat)])
(data Bad : Type
[bad : ((Bad -> Bad) -> Bad)])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment