158 lines
3.1 KiB
Markdown
158 lines
3.1 KiB
Markdown
# 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
|
|
```
|