(deftype (Maybe a) (Just [a]) (Nothing [])) (doc Maybe "is a data type to represent optional values. It has two constructors, `(Just )` and `Nothing`, and provides many functions to wrap and unwrap values.") (defmodule Maybe (doc apply "applies a function to the value inside `a` if it is a `Just`, and wraps it up again. If it is `Nothing`, it is just returned.") (defn apply [a f] (match a (Nothing) (Nothing) (Just x) (Just (~f x)))) (doc unsafe-from "is an unsafe unwrapper that will get the value from a `Just`. If `a` is `Nothing`, a runtime error will be generated.") (defn unsafe-from [a] (match a (Just x) x)) (doc from "is an unwrapper that will get the value from a `Just`, or a default value if a `Nothing` is passed.") (defn from [a dflt] (match a (Nothing) dflt (Just x) x)) (doc or-zero "is an unwrapper that will get the value from a `Just`, or build a value using `zero` if a `Nothing` is passed.") (defn or-zero [a] (match a (Nothing) (zero) (Just x) x)) (doc just? "checks whether the given value `a` is a `Just`. It is the inverse of [`nothing?`](#nothing?).") (defn just? [a] (match-ref a (Nothing) false (Just x) true)) (doc nothing? "checks whether the given value `a` is a `Nothing`. It is the inverse of [`just?`](#just?).") (defn nothing? [a] (match-ref a (Nothing) true (Just x) false)) (doc = "equality is defined as the equality of both the constructor and the contained value, i.e. `(Just 1)` and `(Just 1)` are the same, but `(Just 1)` and `(Just 2)` are not.") (defn = [a b] (match-ref a (Nothing) (nothing? b) (Just x) (match-ref b (Nothing) false (Just y) (= x y)))) (implements = Maybe.=) (doc unsafe-ptr "Creates a `(Ptr a)` from a `(Maybe a)`. If the `Maybe` was `Nothing`, this function will return a `NULL` value.") (defn unsafe-ptr [a] (match-ref a (Nothing) NULL (Just _) ((the (Fn [(Ref (Maybe a))] (Ptr a)) Unsafe.coerce) a))) (doc from-ptr "Creates a `(Maybe a)` from a `(Ptr a)`. If the `Ptr` was `NULL`, this function will return `Nothing`.") (defn from-ptr [a] (if (null? a) (Nothing) (Just @(Pointer.to-ref a)))) (doc zero "returns `Nothing`.") (defn zero [] (Nothing)) (implements zero Maybe.zero) )