; Iter 15g — fifth stdlib module: first 3-way cross-module fn set.
; Imports std_list, std_either, std_pair simultaneously. All three
; combinators dispatch over List<Either<e, a>>; partition_eithers
; additionally returns Pair<List<e>, List<a>>. Stresses
; monomorphisation across List × Either × Pair, cross-module ctor
; resolution at qualified term-ctor sites, and the 16a desugar
; layer at depth-2 nested Ctor patterns (in `lefts` / `rights`).

(module std_either_list

  (import std_list)
  (import std_either)
  (import std_pair)

  (fn lefts
    (doc "Project the Left payloads of a list of Eithers into a List<e>. Order-preserving. Uses the 16a nested-Ctor pattern to inline the inner Either dispatch within each Cons arm; the trailing wildcard arm seals the desugar's fall-through chain into a List<e> rather than the synthetic Unit fallback.")
    (type
      (forall (vars e a)
        (fn-type
          (params (own (con List (con Either e a))))
          (ret (own (con List e))))))
    (params xs)
    (body
      (match xs
        (case (pat-ctor Cons (pat-ctor Left l) t)
          (term-ctor List Cons l (app lefts t)))
        (case (pat-ctor Cons (pat-ctor Right _) t)
          (app lefts t))
        (case _ (term-ctor List Nil)))))

  (fn rights
    (doc "Project the Right payloads of a list of Eithers into a List<a>. Symmetric to lefts; same nested-Ctor + wildcard-tail pattern shape.")
    (type
      (forall (vars e a)
        (fn-type
          (params (own (con List (con Either e a))))
          (ret (own (con List a))))))
    (params xs)
    (body
      (match xs
        (case (pat-ctor Cons (pat-ctor Left _) t)
          (app rights t))
        (case (pat-ctor Cons (pat-ctor Right r) t)
          (term-ctor List Cons r (app rights t)))
        (case _ (term-ctor List Nil)))))

  (fn partition_eithers
    (doc "Partition a list of Eithers into a Pair<List<e>, List<a>>: lefts on the left, rights on the right. Single pass via direct recursion; the recursive result is destructured once and the head dispatches into the matching side.")
    (type
      (forall (vars e a)
        (fn-type
          (params (own (con List (con Either e a))))
          (ret (own (con Pair (con List e) (con List a)))))))
    (params xs)
    (body
      (match xs
        (case (pat-ctor Nil)
          (term-ctor Pair MkPair
            (term-ctor List Nil)
            (term-ctor List Nil)))
        (case (pat-ctor Cons h t)
          (let rest (app partition_eithers t)
            (match rest
              (case (pat-ctor MkPair ls rs)
                (match h
                  (case (pat-ctor Left l)
                    (term-ctor Pair MkPair
                      (term-ctor List Cons l ls)
                      rs))
                  (case (pat-ctor Right r)
                    (term-ctor Pair MkPair
                      ls
                      (term-ctor List Cons r rs))))))))))))
