Skip to content

Instantly share code, notes, and snippets.

@pedrofurla
Last active August 29, 2015 14:00
Show Gist options
  • Save pedrofurla/11161049 to your computer and use it in GitHub Desktop.
Save pedrofurla/11161049 to your computer and use it in GitHub Desktop.
ElapsedTime[A,CC[_]], Functor scalaz instance on CC[_] or NEL
object YetAnother2 {
import scalaz._
import Scalaz._
case class ElapsedTime[A, CC[_]](time: CC[A])
object ElapsedTime {
type ET_A[CC[_]] = {
type λ[A]=ElapsedTime[A, CC]
}
type NEL[A] = NonEmptyList[A]
type ET_A_NEL = {
type λ[A]=ElapsedTime[A, NEL]
}
/*implicit def canBeFunctor[CC[_]](implicit evf: Functor[CC]) = new Functor[ET_A[CC]#λ] {
def map[A,B](fa: ElapsedTime[A,CC])(f: A => B): ElapsedTime[B,CC] = ElapsedTime[B,CC](evf.map(fa.time)(f))
}*/
implicit def canBeFunctor2 = new Functor[ET_A_NEL#λ] { // Tried to specialize on NEL, no luck
def map[A,B](fa: ElapsedTime[A,NEL])(f: A => B): ElapsedTime[B,NEL] = ElapsedTime[B,NEL](fa.time.map(f))
}
implicitly[Functor[ET_A_NEL#λ]]
ElapsedTime(NonEmptyList.nels(1,2,3)).map(_+1)
/* Above line causes
[error] /Users/pedrofurla/dev/projects/slick/slick-perf/src/main/scala/experiments/ScalazExperiments.scala:191:
Implicit not found: scalaz.Unapply[scalaz.Functor, YetAnother2.ElapsedTime[Int,scalaz.NonEmptyList]].
Unable to unapply type `YetAnother2.ElapsedTime[Int,scalaz.NonEmptyList]` into a type constructor of kind `M[_]` that is
classified by the type class `scalaz.Functor`.
Check that the type class is defined by compiling `implicitly[scalaz.Functor[type constructor]]` and review the implicits
in object Unapply, which only cover common type 'shapes.'
[error] ElapsedTime(NonEmptyList.nels(1,2,3)).map(_+1)
[error] ^
[error] one error found
*/
}
}
@pedrofurla
Copy link
Author

implicit def ToFunctorOpsLocal2[A](v: ElapsedTime[A,NEL]): FunctorOps[ET_A_NEL#λ, A] =
        new FunctorOps[ET_A_NEL#λ,A] {
          def self = v; implicit def F: Functor[ET_A_NEL#λ] = implicitly[Functor[ET_A_NEL#λ]]
        }

Does the "trick". But implicit resolution doesn't work outside cross-companion objects.

@pedrofurla
Copy link
Author

Removing TOFunctorOps... and adding:

      implicit def unapplyMA[TC[_[_]],  A0](implicit TC0: TC[ET_A_NEL#λ]): Unapply[TC, ET_A_NEL#λ[A0]] {
         type M[X] = ET_A_NEL#λ[X] // M0[X]
         type A = A0
       } = new Unapply[TC, ET_A_NEL#λ[A0]] {
         import scalaz.Leibniz._
         type M[X] = ET_A_NEL#λ[X]
         type A = A0
         def TC = TC0
         def leibniz = refl
       }

Works. There must be a easier way.

@pedrofurla
Copy link
Author

Replacing the above with

implicit def unapplyFunctorEt[TC[_[_]], A0](implicit TC0: TC[ET_A_NEL#λ]) = Unapply.unapplyMA[TC, ET_A_NEL#λ, A0]

Also works.

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