Last active
October 26, 2018 22:32
-
-
Save LukaJCB/ab1210548e829ae667af007d04cf2f05 to your computer and use it in GitHub Desktop.
Semiringal Functors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package algebraic | |
import simulacrum._ | |
import Semiringal.ops._ | |
@typeclass | |
trait Semigroup[A] { | |
def combine(x: A, y: A): A | |
} | |
@typeclass | |
trait Monoid[A] extends Semigroup[A] { | |
def unit: A | |
} | |
@typeclass | |
trait AdditiveSemigroup[A] { | |
def +(x: A, y: A): A | |
} | |
@typeclass | |
trait AdditiveMonoid[A] extends AdditiveSemigroup[A] { | |
def zero: A | |
} | |
@typeclass | |
trait MultiplicativeSemigroup[A] { | |
def *(x: A, y: A): A | |
} | |
@typeclass | |
trait MultiplicativeMonoid[A] extends MultiplicativeSemigroup[A] { | |
def one: A | |
} | |
@typeclass | |
trait Semiring[A] extends MultiplicativeMonoid[A] with AdditiveMonoid[A] | |
@typeclass | |
trait MultiplicativeSemigroupal[F[_]] { | |
/** Combine both values in a product type */ | |
def <*>[A, B](fa: F[A], fb: F[B]): F[(A, B)] | |
} | |
@typeclass | |
trait AdditiveSemigroupal[F[_]] { | |
/** Combine both values in a sum type */ | |
def <+>[A, B](fa: F[A], fb: F[B]): F[Either[A, B]] | |
} | |
@typeclass | |
trait AdditiveMonoidal[F[_]] extends AdditiveSemigroupal[F] { | |
/** Nothing is the additive identity */ | |
def nothing: F[Nothing] | |
} | |
@typeclass | |
trait MultiplicativeMonoidal[F[_]] extends MultiplicativeSemigroupal[F] { | |
/** Unit is the multiplicative identity */ | |
def unit: F[Unit] | |
} | |
@typeclass | |
trait Semiringal[F[_]] extends MultiplicativeMonoidal[F] with AdditiveMonoidal[F] | |
case class Const[A, B](getConst: A) | |
object Const { | |
implicit def constSemiringal[A: Semiring] = new Semiringal[Const[A, ?]] { | |
def <+>[A, B](fa: Const[A, A], fb: Const[A, B]): Const[A, Either[A, B]] = | |
Const(fa.getConst + fb.getConst) | |
def <*>[A, B](fa: Const[A, A], fb: Const[A, B]): Const[A, (A, B)] = | |
Const(fa.getConst * fb.getConst) | |
def unit: Const[A, Unit] = | |
Const(Semiring[A].one) | |
def nothing: Const[A, Nothing] = | |
Const(Semiring[A].zero) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment