# Queue — foundational two-list FIFO for Bend.
# Publish entry for this package. Depends only on Base (does not reimplement List).
#
# Encoding: front + rear (rear stored reversed). Amortized O(1) enqueue/dequeue
# via Queue.norm (rotate rear→front when front is empty).
# Quantity: Queue is Kind(a), same convention as List/Maybe.
import Base
type Queue is Kind(a):
Q{front: List, rear: List}
# Dequeue view: head + rest queue (Kind-friendly; A & Queue is Type, not Kind(a)).
type Queue.Deq is Kind(a):
HD{head: A, rest: Queue}
def Queue.empty(a, -A: Kind(a)) -> Queue:
Q{Nil{}, Nil{}}
def Queue.enqueue(a, -A: Kind(a), q: Queue, x: A) -> Queue:
match q:
case Q{f, r}:
Q{f, x <> r}
# When front is empty, reverse rear into front (and clear rear).
def Queue.norm(a, -A: Kind(a), q: Queue) -> Queue:
match q:
case Q{f, r}:
match f:
case Nil{}:
Q{List.reverse(a, A, r), Nil{}}
case h <> t:
Q{h <> t, r}
def Queue.dequeue.go(a, -A: Kind(a), q: Queue) -> Maybe>:
match q:
case Q{f, r}:
match f:
case Nil{}:
None{}
case h <> t:
Some{HD{h, Q{t, r}}}
def Queue.dequeue(a, -A: Kind(a), q: Queue) -> Maybe>:
Queue.dequeue.go(a, A, Queue.norm(a, A, q))
def Queue.peek.go(a, -A: Kind(a), q: Queue) -> Maybe:
match q:
case Q{f, r}:
match f:
case Nil{}:
None{}
case h <> t:
Some{h}
def Queue.peek(a, -A: Kind(a), q: Queue) -> Maybe:
Queue.peek.go(a, A, Queue.norm(a, A, q))
def Queue.is_empty(a, -A: Kind(a), q: Queue) -> Bool:
match q:
case Q{f, r}:
match f:
case Nil{}:
List.is_empty(a, A, r)
case h <> t:
False{}
def Queue.length(a, -A: Kind(a), q: Queue) -> Nat:
match q:
case Q{f, r}:
Nat.add(List.length(a, A, f), List.length(a, A, r))
# FIFO order: front ++ reverse(rear).
def Queue.to_list(a, -A: Kind(a), q: Queue) -> List:
match q:
case Q{f, r}:
List.append(a, A, f, List.reverse(a, A, r))
def Queue.from_list(a, -A: Kind(a), xs: List) -> Queue:
Q{xs, Nil{}}