Files
AILang/examples/std_list.ailx
T
Brummel ee5807d73c Iter 15h — std_list extension: take, drop
Adds the two canonical prefix-slicing combinators to std_list.
First fns in std_list to combine `if` + Int arithmetic + recursive
ADT pattern in one body.

  take : forall a. (Int, List<a>) -> List<a>
       — first n elements (or all of xs if shorter than n).
  drop : forall a. (Int, List<a>) -> List<a>
       — list with first n elements removed (Nil if n >= length).

Both use `(if (<= n 0) ...)` as the base-case guard since
literal sub-patterns inside Ctor patterns aren't yet supported
(queued as 16c — would let take/drop collapse the if into the
match).

examples/std_list_more_demo: builds [1, 2, 3, 4, 5] once and
exercises take/drop at n=0, n=mid, n=overflow on each. Expected
output 0, 3, 5, 5, 3, 0 (one per line).

Tests: 95/95 (e2e went from 35 to 36). std_list grew from 10 to
12 combinators; total stdlib 5 modules / 29 combinators. No new
compiler bug surfaced.

Pre-existing std_list defs are byte-identical (verified via diff
on .ailx and round-trip on .ail.json), so the five downstream
importers (std_list_demo, std_list_stress, std_either_list,
std_either_list_demo, list_map_poly) need no regeneration.
2026-05-07 20:05:45 +02:00

197 lines
5.7 KiB
Plaintext

; Iter 15b — second stdlib module: polymorphic singly-linked lists.
; Imports std_maybe so head/tail can return Maybe<a> / Maybe<List<a>>.
; All cross-module references use the qualified form per the Iter 14h
; convention: `std_maybe.Maybe` at type-name slots, `std_maybe.from_maybe`
; for fns. Bare ctor names (`Just`, `Nothing`) stay unqualified — once
; the type is resolved the ctor lookup is unambiguous.
(module std_list
(import std_maybe)
(data List (vars a)
(doc "Polymorphic singly-linked list: Nil or Cons<a, List<a>>.")
(ctor Nil)
(ctor Cons a (con List a)))
(fn fold_left
(doc "Tail-recursive left fold. The recursive call is in tail position and is marked.")
(type
(forall (vars a b)
(fn-type
(params (fn-type (params b a) (ret b))
b
(con List a))
(ret b))))
(params f acc xs)
(body
(match xs
(case (pat-ctor Nil) acc)
(case (pat-ctor Cons h t)
(tail-app fold_left f (app f acc h) t)))))
(fn fold_right
(doc "Right fold. Constructor-blocked: the recursive call is the second arg of f, NOT a tail position.")
(type
(forall (vars a b)
(fn-type
(params (fn-type (params a b) (ret b))
b
(con List a))
(ret b))))
(params f acc xs)
(body
(match xs
(case (pat-ctor Nil) acc)
(case (pat-ctor Cons h t)
(app f h (app fold_right f acc t))))))
(fn length
(doc "Length via fold_left. The accumulating lambda ignores the element and increments the counter.")
(type
(forall (vars a)
(fn-type
(params (con List a))
(ret (con Int)))))
(params xs)
(body
(app fold_left
(lam (params (typed c (con Int)) (typed _ a))
(ret (con Int))
(body (app + c 1)))
0
xs)))
(fn reverse
(doc "Reverse via fold_left with a flipping accumulator. Tail-recursive by virtue of the fold_left call.")
(type
(forall (vars a)
(fn-type
(params (con List a))
(ret (con List a)))))
(params xs)
(body
(app fold_left
(lam (params (typed acc (con List a)) (typed h a))
(ret (con List a))
(body (term-ctor List Cons h acc)))
(term-ctor List Nil)
xs)))
(fn is_empty
(doc "True iff the list is Nil.")
(type
(forall (vars a)
(fn-type
(params (con List a))
(ret (con Bool)))))
(params xs)
(body
(match xs
(case (pat-ctor Nil) true)
(case (pat-ctor Cons _ _) false))))
(fn head
(doc "Returns Just<a> of the first element, or Nothing for an empty list. Cross-module Maybe.")
(type
(forall (vars a)
(fn-type
(params (con List a))
(ret (con std_maybe.Maybe a)))))
(params xs)
(body
(match xs
(case (pat-ctor Nil) (term-ctor std_maybe.Maybe Nothing))
(case (pat-ctor Cons h _) (term-ctor std_maybe.Maybe Just h)))))
(fn tail
(doc "Returns Just<List<a>> of the tail, or Nothing for an empty list.")
(type
(forall (vars a)
(fn-type
(params (con List a))
(ret (con std_maybe.Maybe (con List a))))))
(params xs)
(body
(match xs
(case (pat-ctor Nil) (term-ctor std_maybe.Maybe Nothing))
(case (pat-ctor Cons _ t) (term-ctor std_maybe.Maybe Just t)))))
(fn append
(doc "Concatenate two lists. Constructor-blocked recursion: the recursive call is inside Cons, NOT a tail.")
(type
(forall (vars a)
(fn-type
(params (con List a) (con List a))
(ret (con List a)))))
(params xs ys)
(body
(match xs
(case (pat-ctor Nil) ys)
(case (pat-ctor Cons h t)
(term-ctor List Cons h (app append t ys))))))
(fn map
(doc "Polymorphic map. Constructor-blocked recursion.")
(type
(forall (vars a b)
(fn-type
(params (fn-type (params a) (ret b))
(con List a))
(ret (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 filter
(doc "Keep elements where p is true. Constructor-blocked when p holds; non-tail recursive call when p is false.")
(type
(forall (vars a)
(fn-type
(params (fn-type (params a) (ret (con Bool)))
(con List a))
(ret (con List a)))))
(params p xs)
(body
(match xs
(case (pat-ctor Nil) (term-ctor List Nil))
(case (pat-ctor Cons h t)
(if (app p h)
(term-ctor List Cons h (app filter p t))
(app filter p t))))))
(fn take
(doc "First n elements of xs (or all of xs if it has fewer than n).")
(type
(forall (vars a)
(fn-type
(params (con Int) (con List a))
(ret (con List a)))))
(params n xs)
(body
(if (app <= n 0)
(term-ctor List Nil)
(match xs
(case (pat-ctor Nil) (term-ctor List Nil))
(case (pat-ctor Cons h t)
(term-ctor List Cons h (app take (app - n 1) t)))))))
(fn drop
(doc "All elements of xs after the first n (or Nil if xs has fewer than n elements).")
(type
(forall (vars a)
(fn-type
(params (con Int) (con List a))
(ret (con List a)))))
(params n xs)
(body
(if (app <= n 0)
xs
(match xs
(case (pat-ctor Nil) (term-ctor List Nil))
(case (pat-ctor Cons _ t)
(app drop (app - n 1) t)))))))