typelevel / typelevel/cats

Invariant super class of Alternative and Decidable

Open
#2,620 28 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
5.5k
Forks
1.2k
Avg merge
2d 10h
Merged PRs (30d)
5

Description

This ties into #1935, but also #2400 and #1932.

I think we could do a lot better with the Alternative hierarchy and the Decidable PR shows, it might need some binary breaking changes.

Ideally we could replicate the *Monoidal hierarchy, but using sum types instead. Then at the end we'd have InvariantSemiringal and have Alternative and Decidable extend from that.

Some code I came up with (names are not final by any means):

// Invariant hierarchy

@typeclass
trait InvariantAddSemigroupal[F[_]] {
  def invariant: Invariant[F]
  def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]]
}

@typeclass
trait InvariantAddMonoidal[F[_]] extends InvariantAddSemigroupal[F] {
  def empty[A]: F[A]
}

@typeclass 
trait InvariantSemiringal[F[_]] extends InvariantAddMonoidal[F] with InvariantMonoidal[F]

// Covariant hierarchy

@typeclass
trait SemigroupK[F[_]] extends InvariantAddSemigroupal[F] {
  def combineK[A](x: F[A], y: F[A]): F[A]
  def functor: Functor[F]

  override def invariant: Invariant[F] = functor
  override def sum[A, B](fa: F[A], fb: F[B]): F[Either[A, B]] =
     combineK(functor.map(fa)(Left(_)), functor.map(fb)(Right(_)))
}

@typeclass
trait MonoidK[F[_]] extends SemigroupK[F] with InvariantAddMonoidal[F]

@typeclass
trait Alternative[F] extends MonoidK[F] with InvariantSemiringal[F]

// Contravariant hierarchy

@typeclass
trait ContravariantAddSemigroupal[F[_]] extends InvariantAddSemigroupal[F] {
  def contravariant: Contravariant[F]

  override def invariant: Invariant[F] = contravariant
}

@typeclass
trait ContravariantAddMonoidal[F[_]] extends ContravariantAddSemigroupal[F] with InvariantAddMonoidal[F] 

@typeclass
trait Decidable[F] extends ContravariantAddMonoidal[F] with InvariantSemiringal[F]

I've also written about this quite a bit in this blog post: https://typelevel.org/blog/2018/11/02/semirings.html

I made a funky looking diagram real quick:

monoidals

As to why this is useful, I think this offers a really great API for codec combinators when working with e.g. circe, scodec or recently skunk.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the existing Alternative and Decidable hierarchies, then review related issues #1935, #2400, and #1932 and the linked semirings blog post. Done would require an agreed hierarchy design, including names and binary-compatibility decisions; the issue does not identify files or tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.