================================================================================
plain adt: empty
================================================================================

data A

---

(haskell (adt (type)))

================================================================================
plain adt: one nullary con
================================================================================

data A = A

---

(haskell (adt (type) (constructors (data_constructor (constructor)))))

================================================================================
plain adt: one unary con
================================================================================

data A = A A

---

(haskell (adt (type) (constructors (data_constructor (constructor) (type_name (type))))))

================================================================================
plain adt: strict
================================================================================

data A = A !A !(A A)

---

(haskell
 (adt
  (type)
  (constructors
   (data_constructor
    (constructor)
    (strict_type (type_name (type)))
    (strict_type (type_parens (type_apply (type_name (type)) (type_name (type)))))))))

================================================================================
plain adt: tyvars
================================================================================

data A a a a = A a !a [a]

---

(haskell
 (adt
  (type)
  (type_variable)
  (type_variable)
  (type_variable)
  (constructors
   (data_constructor (constructor) (type_name (type_variable)) (strict_type (type_name (type_variable))) (type_list (type_name (type_variable)))))))

================================================================================
plain adt: unpack strict
================================================================================

data A = A {-# unpack #-} !A

---

(haskell
 (adt
  (type)
  (constructors
   (data_constructor (constructor) (pragma) (strict_type (type_name (type)))))))

================================================================================
plain adt: record
================================================================================

data A a = A { a :: A, a, a :: A, a :: {-# unpack #-} !a, a :: !A }

---

(haskell
 (adt
  (type)
  (type_variable)
  (constructors
   (data_constructor_record
    (constructor)
    (record_fields
     (field (variable) (type_name (type)))
     (comma)
     (field (variable) (comma) (variable) (type_name (type)))
     (comma)
     (field (variable) (pragma) (strict_type (type_name (type_variable))))
     (comma)
     (field (variable) (strict_type (type_name (type)))))))))

================================================================================
plain adt: multiple cons
================================================================================

data A = A | A A | A !A A

---

(haskell
 (adt
  (type)
  (constructors
   (data_constructor (constructor))
   (data_constructor (constructor) (type_name (type)))
   (data_constructor (constructor) (strict_type (type_name (type))) (type_name (type))))))

================================================================================
plain adt: multiple records
================================================================================

data A =
  A { a :: A, a :: !A }
  |
  A { a :: A }

---

(haskell
 (adt
  (type)
  (constructors
   (data_constructor_record
    (constructor)
    (record_fields
     (field (variable) (type_name (type)))
     (comma)
     (field (variable) (strict_type (type_name (type))))))
   (data_constructor_record
    (constructor)
    (record_fields
     (field (variable) (type_name (type))))))))

================================================================================
plain adt: deriving basic
================================================================================

data A = A deriving A

---

(haskell
 (adt
  (type)
  (constructors (data_constructor (constructor)))
  (deriving (type))))

================================================================================
plain adt: deriving empty
================================================================================

data A deriving A

data A
  deriving A

---

(haskell
 (adt (type) (deriving (type)))
 (adt (type) (deriving (type))))

================================================================================
plain adt: deriving multi, strategy
================================================================================

data A = A deriving (A, A) deriving stock (A)

---

(haskell
 (adt
  (type)
  (constructors (data_constructor (constructor)))
  (deriving (constraint (class_name (type))) (comma) (constraint (class_name (type))))
  (deriving (deriving_strategy) (constraint (class_name (type))))))

================================================================================
plain adt: deriving via
================================================================================

data A = A deriving (A) via (A A)

---

(haskell
 (adt
  (type)
  (constructors (data_constructor (constructor)))
  (deriving
   (constraint (class_name (type)))
   (via (type_parens (type_apply (type_name (type)) (type_name (type))))))))

================================================================================
plain adt: deriving on newline, multiple
================================================================================

data A =
  A
  deriving A
  deriving A
data A =
  A
  deriving A
  deriving A

---

(haskell
 (adt
  (type)
  (constructors (data_constructor (constructor)))
  (deriving (type))
  (deriving (type)))
 (adt
  (type)
  (constructors (data_constructor (constructor)))
  (deriving (type))
  (deriving (type))))

================================================================================
plain adt: deriving with forall/context
================================================================================

data A = A deriving (∀ a . A => A)

---

(haskell
 (adt
  (type)
  (constructors (data_constructor (constructor)))
  (deriving
   (forall
    (quantifiers (type_variable))
    (context (constraint (class_name (type)))
     (constraint (class_name (type))))))))

================================================================================
plain adt: context
================================================================================

data A a (A a) => A = A
data (A a, A a) => A = A

---

(haskell
 (adt
  (context
   (constraint
    (class_name (type))
    (type_name (type_variable))
    (type_parens (type_apply (type_name (type)) (type_name (type_variable)))))
   )
  (type)
  (constructors (data_constructor (constructor))))
 (adt
  (context
   (constraint (class_name (type)) (type_name (type_variable)))
   (comma)
   (constraint (class_name (type)) (type_name (type_variable)))
  )
  (type)
  (constructors (data_constructor (constructor)))))

================================================================================
plain adt: prim
================================================================================

data A = A !A#

---

(haskell
 (adt
  (type)
  (constructors (data_constructor (constructor) (strict_type (type_name (type)))))))

================================================================================
plain adt: forall
================================================================================

data A = forall a . A | ∀ a . A

---

(haskell
 (adt
  (type)
  (constructors
   (forall (quantifiers (type_variable)))
   (data_constructor (constructor))
   (forall (quantifiers (type_variable)))
   (data_constructor (constructor)))))

================================================================================
plain adt: con context
================================================================================

data A = ∀ a . A a => A

---

(haskell
 (adt
  (type)
  (constructors
   (forall (quantifiers (type_variable)))
   (context (constraint (class_name (type)) (type_name (type_variable))))
   (data_constructor (constructor)))))

================================================================================
plain adt: type_variable kind
================================================================================

data A (a :: * -> 'A)

---

(haskell
 (adt
  (type)
  (annotated_type_variable
   (type_variable)
   (fun (type_star) (type_name (promoted (type)))))))

================================================================================
plain adt: signature
================================================================================

data A :: (k -> '[ 'A]) -> *

---

(haskell
 (adt
  (type)
  (fun
   (type_parens
    (fun
     (type_name (type_variable))
     (promoted (type_list (type_name (promoted (type)))))))
   (type_star))))

================================================================================
plain adt: type operator varsym
================================================================================

data a +++ b = a :+++ b

---

(haskell
 (adt
  (type_infix (type_variable) (type_operator) (type_variable))
  (constructors
   (data_constructor_infix
    (type_name (type_variable))
    (constructor_operator)
    (type_name (type_variable))))))

================================================================================
plain adt: type operator consym
================================================================================

data a :<- b = a :<- b

---

(haskell
 (adt
  (type_infix (type_variable) (constructor_operator) (type_variable))
  (constructors
   (data_constructor_infix
    (type_name (type_variable))
    (constructor_operator)
    (type_name (type_variable))))))
