simulacrum icon indicating copy to clipboard operation
simulacrum copied to clipboard

Add support for type classes that abstract over type constructors of 2 type params

Open mpilquist opened this issue 10 years ago • 10 comments

E.g., bifunctors, profunctors, arrows

mpilquist avatar Jan 17 '15 20:01 mpilquist

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 avatar Feb 22 '15 23:02 drdozer

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.

drdozer avatar Mar 06 '15 08:03 drdozer

+1 I'd love to have this ability!

malcolmgreaves avatar Sep 04 '15 17:09 malcolmgreaves

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
}

paulp avatar Nov 21 '15 05:11 paulp

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

yilinwei avatar May 23 '16 20:05 yilinwei

@yilinwei That would be awesome :)

mpilquist avatar May 23 '16 20:05 mpilquist

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.

yilinwei avatar May 27 '16 00:05 yilinwei

Does this mean this ticket can be closed?

Does simulacrum now support this as well?

@typeclass sealed trait AsymEquals[L,R]

cvogt avatar Jun 19 '16 18:06 cvogt

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

cvogt avatar Jun 19 '16 18:06 cvogt

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

yilinwei avatar Jun 19 '16 20:06 yilinwei