ava/standard-type-classes.md

3.1 KiB

Standard Type Classes

--- Associative binary operation.
--- **Associative**: `combine(x, combine(y, z)) = combine(combine(x, y), z)`
given A
class Semigroup
    fn combine(x: A, y: A): A
end class

--- **Empty Identity**: `combine(x, empty()) = combine(empty(), x) = x`
given A :: Semigroup
class Monoid
    fn empty() => A
end class

--- Type class for type constructors which can be mapped over.
---
--- ## Laws
---
--- **Composition**: `fa -> f -> g = fa -> (f ∘ g)`
--- **Identity**: `fa -> ((x) => x) = fa`
given F[*]
class Functor
    --- Transform some wrapped data from one type to another, preserving the
    --- wrapper.
    ---
    --- @tparam A The type of input data.
    --- @tparam B The type of output data.
    --- @param fa The functor input.
    --- @param f The function to transform data from `A` to `B`.
    given [A, B]
    fn map: (fa: F[A])(f: (A) => B) => F[B]
end class

-- Need Laws
given F[*] :: Functor
class Apply
    given A, B
    fn ap: (ff: F[(A) => B])(fa: F[A]) => F[B]
end class

-- Need Laws
given F[*] :: Apply
class Applicative
    given A
    fn pure: (value: A) => F[A]

    fn unit: () => F[()]
        pure(())
    end fn
end class

--- Any Applicative satisfies Functor.
given F[*] :: Applicative
instance Functor[F]
    given A, B
    fn map: (fa: F[A])(f: (A) => B) => F[B]
        ap(pure(f))(fa)
    end fn
end instance

given F[*] :: Apply
class FlatMap
    given A, B
    fn fmap: (fa: F[A])(f: (A) => F[B]) => F[B]

    given A
    fn flatten: (ffa: F[F[A]]) => F[A]
        fmap(ffa)((fa) => fa)
    end fn
end class

given F[*] :: FlatMap, Applicative
class Monad
end class

--- Any Monad satisfies Functor.
--- Note for type class spec, must account for "override" precedence
given F[*] :: Applicative
instance Functor[F]
    fn map: (fa: F[A])(f: (A) => B) => F[B]
        fmap(fa)((a) => pure(f(a)))
    end fn
end instance

given F[*, *]
class Bifunctor
    def bimap[A, B, C, D](fab: F[A, B])(f: A => C, g: B => D): F[C, D]

    given A, B, C, D
    fn bimap(fab: F[A, B])(f: (A) => C, g: (B) => D) => F[C, D]
end class

given F[*] :: Functor
class CoFlatMap
    given A, B
    fn cofmap: (fa: F[A])(f: (F[A]) => B) => F[B]

    given A
    fn coflatten: (fa: F[A]) => F[F[A]]
        cofmap(fa)((fa) => fa)
    end fn
end class

given F[*] :: CoFlatMap
class CoMonad
    given A
    fn extract: (fa: F[A]) => A
end class

given A
class Show
    fn show: (value: A) => String
end class

given A, B
class Eq
    fn eq: (x: A, y: B) => Boolean

    fn neq: (x: A, y: B) => Boolean
        not(eq(x, y))
    end fn

    infix =: (x: A, y: B) => Boolean
        eq(x, y)
    end infix

    infix !=: (x: A, y: B) => Boolean
        neq(x, y)
    end infix
end class

enum Comparison
    object LessThan
    object EqualTo
    object GreaterThan
end enum

given A
class Compare
    fn compare: (x: A, y: A) => Comparison
end class

given A
instance Eq[A, A]
    fn eq: (x: A, y: A) => Boolean
        match compare(x, y)
            case EqualTo => true
            case _ => false
    end fn
end instance

given A
class HashCode
    fn hash_code(data: A) => Int32
end class