# 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 ```