================================================================================
gadt: empty
================================================================================

data A where

---

(haskell (adt (type) (where)))

================================================================================
gadt: basic
================================================================================

data A a where
  A :: A -> !(A a) ->
    A a
  A :: {-# unpack #-} A -> A a

---

(haskell
 (adt
  (type)
  (type_variable)
  (where)
  (gadt_constructor
   (constructor)
   (fun
    (type_name (type))
    (fun
     (strict_type (type_parens (type_apply (type_name (type)) (type_name (type_variable)))))
     (type_apply (type_name (type)) (type_name (type_variable))))))
  (gadt_constructor
   (constructor)
   (pragma)
   (fun
    (type_name (type))
    (type_apply (type_name (type)) (type_name (type_variable)))))))

================================================================================
gadt: record
================================================================================

data A where
  A :: { a :: A, a :: !A } -> A

---

(haskell
 (adt
  (type)
  (where)
  (gadt_constructor
   (constructor)
   (record_fields
    (field (variable) (type_name (type)))
    (comma)
    (field (variable) (strict_type (type_name (type)))))
   (type_name (type)))))

================================================================================
gadt: signature
================================================================================

data A :: [*] -> * where

---

(haskell
 (adt
  (type)
  (fun
   (type_list (type_star))
   (type_star))
  (where)))

================================================================================
gadt: context
================================================================================

data A a => A where

---

(haskell
 (adt
  (context (constraint (class_name (type)) (type_name (type_variable))))
  (type)
  (where)))

================================================================================
gadt: con context
================================================================================

data A where
  A :: A a => A

---

(haskell
 (adt
  (type)
  (where)
  (gadt_constructor
   (constructor)
   (context
    (constraint (class_name (type)) (type_name (type_variable)))
   )
   (type_name (type)))))

================================================================================
gadt: forall
================================================================================

data A where
  A :: ∀ a . A

---

(haskell
 (adt
  (type)
  (where)
  (gadt_constructor
   (constructor)
   (forall (quantifiers (type_variable)))
   (type_name (type)))))

================================================================================
gadt: deriving
================================================================================

data A where
  A :: A
  deriving A

---

(haskell
 (adt
  (type)
  (where)
  (gadt_constructor (constructor) (type_name (type)))
  (deriving (type))))

================================================================================
gadt: symbolic operator
================================================================================

data a +++ b where
  (:+++) :: a -> b -> a +++ b

---

(haskell
 (adt
  (type_infix (type_variable) (type_operator) (type_variable))
  (where)
  (gadt_constructor
   (constructor_operator)
   (fun
    (type_name (type_variable))
    (fun
     (type_name (type_variable))
     (type_infix
      (type_name (type_variable))
      (type_operator)
      (type_name (type_variable))))))))

================================================================================
gadt: newtype
================================================================================

newtype A where
  A :: A

---

(haskell (newtype (type) (where) (gadt_constructor (constructor) (type_name (type)))))

================================================================================
gadt: symbolic type
================================================================================

data (:#) a where

---

(haskell (adt (constructor_operator) (type_variable) (where)))
