8.18
| | (data type-signature |  | maybe-prefix-form |  | clause ...) | 
 | 
|  | 
| | type-signature |  | = |  | type-name |  |  |  | | |  | (type-name type-variable ...) |  |  |  |  |  |  |  | maybe-prefix-form |  | = |  | #:prefix |  |  |  | | |  | #:prefix prefix-id |  |  |  |  |  |  |  | clause |  | = |  | [name param ...] |  |  |  |  |  |  |  | param |  | = |  | type |  |  |  | | |  | [param-name type] | 
 | 
Just like the data type you would see in Haskell and ML, which supports parametric polymorphism. The prefix form is for namespacing the constructor of data type. The following is a normal usage, the constructors are all without namespacing.
| (data expr | 
| [Var (name : Symbol)] | 
| [abs (name : Symbol) (body : expr)] | 
| [app (fn : expr) (arg : expr)] | 
| [pi (name : Symbol) (e : expr) (body : expr)] | 
| [type (level : Integer)] | 
| [nat] | 
| [zero] | 
| [succ (n : expr)] | 
| [rec expr expr expr expr] | 
| [id expr expr expr] | 
| [refl expr] | 
| [J expr expr expr expr expr expr]) | 
To have namespacing prefix, use the following code. The data type still Expr here, but the constructors will get E: prefix automatically.
| (data Expr #:prefix E | 
| [Int Integer] | 
| [Add Expr Expr]) | 
|  | 
| (: Eval : Expr -> Integer) | 
| (define (Eval e) | 
| (match e | 
| [(E:Int v) v] | 
| [(E:Add l r) (+ (Eval l) (Eval r))])) | 
|  | 
| (Eval (E:Add (E:Int 1) (E:Int 2))) | 
And if you require #:prefix but didn’t provide an identifier, it will use data type LIST as prefix.
| (data (LIST T) #:prefix | 
| [Nil] | 
| [Cons T (LIST T)]) | 
|  | 
| (: Len : (∀ (T) (LIST T) -> Natural)) | 
| (define (Len L) | 
| (match L | 
| [(LIST:Nil) 0] | 
| [(LIST:Cons t Tail) (add1 (Len Tail))])) | 
|  | 
| (Len (LIST:Cons #t (LIST:Nil))) |