New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Divisible and Decideable (contravariant Applicative and co.) #1935

Open
adelbertc opened this Issue Sep 27, 2017 · 21 comments

Comments

Projects
None yet
5 participants
@adelbertc
Member

adelbertc commented Sep 27, 2017

https://hackage.haskell.org/package/contravariant-1.4/docs/Data-Functor-Contravariant-Divisible.html

Example use case: divide can be seen as a way of deriving behavior by splitting a "larger" type in two

@adelbertc adelbertc changed the title from Contravariant Applicative and co. to Add Divisible and Decideable (contravariant Applicative and co.) Sep 27, 2017

@iravid

This comment has been minimized.

Contributor

iravid commented Sep 27, 2017

Yes please! Very useful for encoders

@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Sep 29, 2017

Can you expand a bit on the example use case? I'm not really seeing its usefulness right now

@iravid

This comment has been minimized.

Contributor

iravid commented Sep 29, 2017

Divisible is to Applicative as Contravariant is to Functor.

Let's say that we have an encoder trait:

trait Encoder[T] {
  def encode(t: T): String
}

Encoder has a contravariant functor as it is isomorphic to ? => String.

Given this definition of divisible:

trait Divisible[F[_]] extends Contravariant[F[_]] {
  def contramap2[A, B, C](fa: F[A], fb: F[B])(f: C => (A, B): F[C]
}

I could derive an encoder given two other encoders:

case class Record(i: Int, s: String)
val recEnc: Encoder[Record] = Divisible[Record].contramap2(Encoder[Int], Encoder[String])((rec: Record) => (rec.i, rec.s))
@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Sep 29, 2017

Thanks @iravid, that indeed seems like a useful addition. However, I'm not sure that we'd have a lot of instances. The only one I can come up with right now would be Show and Order. I'm not really sure these are common enough to warrant adding them to core.

Maybe we could add them in some other module? WDYT?

@iravid

This comment has been minimized.

Contributor

iravid commented Sep 29, 2017

I wouldn't mind that, as long as they're available :-)

@adelbertc

This comment has been minimized.

Member

adelbertc commented Sep 29, 2017

Looking at https://hackage.haskell.org/package/contravariant-1.4/docs/Data-Functor-Contravariant-Divisible.html we can define instances for Const, the usual transformer "induction"/"back chaining", Nested, Tuple2K

@stephen-lazaro

This comment has been minimized.

Contributor

stephen-lazaro commented Oct 28, 2017

Would anyone object if I were to try my hand at this? I'd be happy to give it a shot. I can always open it against cats-core for now and then move it over to cats-more if that's the direction folks go.

@kailuowang

This comment has been minimized.

Member

kailuowang commented Oct 28, 2017

This one is more likely to goto cats.more.

@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Jun 9, 2018

This can be closed now after #2034

@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Oct 30, 2018

Actually I closed to early as we do have an analogue to Divisible, but not to Decidable, so I'll reopen this :)

@LukaJCB LukaJCB reopened this Oct 30, 2018

@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Oct 30, 2018

To be honest, it'd be pretty cool to see something like this in Cats:

@typeclass trait Decidable[F[_]] extends ContravariantMonoidal[F] with MonoidK[F] {

  def decide[A, B, C](fa: F[A], fb: F[B])(f: C => Either[A, B]): F[C]

  override def combineK[A](x: F[A], y: F[A]): F[A] =
    decide[A, A, A](x, y)(Right(_))
}

@LukaJCB LukaJCB added the help wanted label Oct 30, 2018

@stephen-lazaro

This comment has been minimized.

Contributor

stephen-lazaro commented Oct 30, 2018

@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Oct 30, 2018

Please feel free to go right ahead :)

@stephen-lazaro

This comment has been minimized.

Contributor

stephen-lazaro commented Oct 30, 2018

@LukaJCB If I wanted to add a dependency on typelevel/algebra would that be acceptable? As far as I can tell, it doesn't exist currently. It would be useful to articulate Semiring / Ring constraints in some cases

@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Oct 30, 2018

I don't think that's in scope right now, there some talks on merging it into the cats repo or maybe even the cats-kernel module, so I propose adding Decidable now and then adding instances using Semiring constraints later :)

@stephen-lazaro

This comment has been minimized.

Contributor

stephen-lazaro commented Oct 30, 2018

Yeah, fair. Makes sense, I'll leave those instances out for now. I'll opt for more specific instances for now and leave a note, so we can at least have things like A => Boolean.

@kailuowang

This comment has been minimized.

Member

kailuowang commented Oct 30, 2018

Is there an issue for merging algebra into cats?

@stephen-lazaro

This comment has been minimized.

Contributor

stephen-lazaro commented Oct 30, 2018

I'm happy to do that if that's something we want, after I finish adding this.

@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Oct 31, 2018

@kailuowang the discussion's mostly been going on in #2041 and typelevel/algebra#218 :)

@LukaJCB

This comment has been minimized.

Collaborator

LukaJCB commented Oct 31, 2018

Decidable might be more tricky to add than I thought a day ago. I don't think we can derive combineK for contravariant and invariant structures, so that means there's no way to extend from SemigroupK :(
Maybe in the future we could add an invariant parent for SemigroupK that could also be a superclass for Decidable.
Possibly someone else has other ideas :)

@stephen-lazaro

This comment has been minimized.

Contributor

stephen-lazaro commented Oct 31, 2018

Hmmm, right. I think for now I might drop the SemigroupK dependency in favor of optimizing for the sum and decide operations.
I imagine that means we can't really add it at a later date, but oh well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment