; Iter 14b design exhibit, finalised in Iter 14c.
; Hash-equivalent to list_map_poly.ail.json (round-trip-tested).

(module list_map_poly

  (data List (vars a)
    (doc "Polymorphic singly-linked list.")
    (ctor Nil)
    (ctor Cons a (con List a)))

  (fn inc
    (doc "Add 1 to an Int.")
    (type (fn-type (params (own (con Int))) (ret (own (con Int)))))
    (params x)
    (body (app + x 1)))

  (fn map
    (doc "Polymorphic map: apply f to every element, recursing on the tail.")
    (type
      (forall (vars a b)
        (fn-type
          (params (own (fn-type (params (own a)) (ret (own b))))
                  (own (con List a)))
          (ret (own (con List b))))))
    (params f xs)
    (body
      (match xs
        (case (pat-ctor Nil)
          (term-ctor List Nil))
        (case (pat-ctor Cons h t)
          (term-ctor List Cons
            (app f h)
            (app map f t))))))

  (fn print_list
    (doc "Print each Int on its own line.")
    (type
      (fn-type
        (params (own (con List (con Int))))
        (ret (own (con Unit)))
        (effects IO)))
    (params xs)
    (body
      (match xs
        (case (pat-ctor Nil)
          (lit-unit))
        (case (pat-ctor Cons h t)
          (seq
            (seq (app print h) (do io/print_str "\n"))
            (tail-app print_list t))))))

  (fn main
    (doc "Map inc over [1,2,3] via polymorphic List, then print: 2,3,4.")
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (app print_list
        (app map inc
          (term-ctor List Cons 1
            (term-ctor List Cons 2
              (term-ctor List Cons 3
                (term-ctor List Nil)))))))))
