Skip to content
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 support for type classes that abstract over type constructors of 2 type params #6

Open
mpilquist opened this issue Jan 17, 2015 · 10 comments

Comments

@mpilquist
Copy link
Member

E.g., bifunctors, profunctors, arrows

@mpilquist mpilquist added this to the 0.3.0 milestone Feb 3, 2015
@drdozer
Copy link

drdozer commented Feb 22, 2015

I have a variant on this. were the first type parameter is important, but the rest are just plumbing. For example:

trait Fold2[T, A1, A2] {
  def fold[X](t: T)(
    f1: A1 => X,
    f2: A2 => X): X
}

The typeclass type here is T. The A1 and A2 types are plumbing to make things work. If we had curried type lists, these would be curried.

The code to generate in the companion looks something like this (abridged):

object Fold2 {
  def apply[T, A1, A2](implicit fold: Fold2[T, A1, A2]): Fold2[T, A1, A2] = fold

  trait Ops[T, A1, A2] {
    def typeClassInstance: Fold2[T, A1, A2]
    def self: T
    def fold[X](
        f1: A1 => X,
        f2: A2 => X): X = typeClassInstance.fold(self)(f1, f2)
  }

  trait ToFold2Ops {
    implicit def toFold2Ops[T, A1, A2](target: T)(implicit tc: Fold2[T, A1, A2]): Ops[T, A1, A2] = new Ops[T, A1, A2] {
      val self = target
      val typeclassInstance = tc
    }
  }

  object ops extends ToFold2Ops
}

@drdozer
Copy link

drdozer commented Mar 6, 2015

And another variant:

  @typeclass trait Equality[T1, T2] {
    @op("===") def equal(lhs: T1, rhs: T2): xs#boolean
    @op("≠") def notEqual(lhs: T1, rhs: T2): xs#boolean
  }

Here, only T1 ever appears on the left, so essentially the same code generation strategy could be used as currently, except that T2 needs to be carried around.

@malcolmgreaves
Copy link

+1 I'd love to have this ability!

@paulp
Copy link
Contributor

paulp commented Nov 21, 2015

The typeclass type here is T. The A1 and A2 types are plumbing to make things work. If we had curried type lists, these would be curried.

We do sort of have curried type lists, or at least a way to make the plumbing depend on the one which matters. Since #21 is now fixed this should be viable in practice.

trait Fold2[T] {
  type A1 
  type A2
  def fold[X](t: T)(
    f1: A1 => X,
    f2: A2 => X): X
}

@mpilquist mpilquist removed this from the 0.3.0 milestone Dec 19, 2015
@yilinwei
Copy link
Contributor

@mpilquist I'm going to take a stab at this tomorrow since I want to tidy up the Arrow package in cats.

@mpilquist
Copy link
Member Author

@yilinwei That would be awesome :)

@yilinwei
Copy link
Contributor

A day or two late, but as promised #59.

wrt to the MonadError use case, that is TC[F[_], E] I think that I'll add that in tomorrow because I think that it should be fairly simple.

@cvogt
Copy link

cvogt commented Jun 19, 2016

Does this mean this ticket can be closed?

Does simulacrum now support this as well?

@typeclass sealed trait AsymEquals[L,R]

@cvogt
Copy link

cvogt commented Jun 19, 2016

FYI: if this is fixed the Readme also needs to be updated at the very bottom

@yilinwei
Copy link
Contributor

yilinwei commented Jun 19, 2016

Not yet - I wanted to think a little about the type traversal before continuing - at the moment tit does TC[F[...]]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants