; Iter 15a — first stdlib module: optional values.
; Polymorphic Maybe with four pure combinators.

(module std_maybe

  (data Maybe (vars a)
    (doc "Polymorphic optional value: either Just<a> or Nothing.")
    (ctor Nothing)
    (ctor Just a))

  (fn from_maybe
    (doc "Project out of Maybe<a> with a default for the Nothing case.")
    (type
      (forall (vars a)
        (fn-type
          (params (own a) (own (con Maybe a)))
          (ret (own a)))))
    (params default m)
    (body
      (match m
        (case (pat-ctor Just x) x)
        (case (pat-ctor Nothing) default))))

  (fn is_some
    (doc "Returns true iff m is Just<_>.")
    (type
      (forall (vars a)
        (fn-type
          (params (borrow (con Maybe a)))
          (ret (own (con Bool))))))
    (params m)
    (body
      (match m
        (case (pat-ctor Just _) true)
        (case (pat-ctor Nothing) false))))

  (fn is_none
    (doc "Returns true iff m is Nothing.")
    (type
      (forall (vars a)
        (fn-type
          (params (borrow (con Maybe a)))
          (ret (own (con Bool))))))
    (params m)
    (body
      (match m
        (case (pat-ctor Just _) false)
        (case (pat-ctor Nothing) true))))

  (fn map_maybe
    (doc "Apply f to the wrapped value, or pass Nothing through.")
    (type
      (forall (vars a b)
        (fn-type
          (params (own (fn-type (params (own a)) (ret (own b))))
                  (own (con Maybe a)))
          (ret (own (con Maybe b))))))
    (params f m)
    (body
      (match m
        (case (pat-ctor Just x)
          (term-ctor Maybe Just (app f x)))
        (case (pat-ctor Nothing)
          (term-ctor Maybe Nothing))))))
