simulacrum icon indicating copy to clipboard operation
simulacrum copied to clipboard

Ops itself should have a proxy type class

Open Atry opened this issue 8 years ago • 1 comments

Suppose we want to store heterogenous types in a Array, and then show them. For type-safety, we can store Show.Ops in the Array

Welcome to the Ammonite Repl 1.0.0
(Scala 2.12.2 Java 1.8.0_131)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi
@ import cats.instances.all._ 
import cats.instances.all._
@ import cats.Show.ops._ 
import cats.Show.ops._
@ import cats.Show 
import cats.Show
@ val harray: Array[Show.AllOps[_]] = Array(toAllShowOps(42), toAllShowOps("foo")) 
harray: Array[Show.AllOps[_]] = Array(cats.Show$ops$$anon$4@e8ce5b1, cats.Show$ops$$anon$4@6101fd7d)
@ for (element <- harray) {
    println(element.show)
  } 
42
foo

However, this does not compile if the foreach body requires a Show type class.

@ def f[A: Show](a: A) = println(a.show)
defined function f
@ harray.foreach(f(_)) 
cmd5.sc:1: could not find implicit value for evidence parameter of type cats.Show[cats.Show.AllOps[_$1]]
val res5 = harray.foreach(f(_))
                           ^

I wonder if it is possible to automatically generate a cats.Show[cats.Show.AllOps[_]] by forwarding abstract method calls to the Ops for @typeclass annotated type classes.

Atry avatar Aug 01 '17 04:08 Atry

It's very possible, but I don't see why Ops makes sense to use here. Especially because not every method on a type class is on an Ops class. Take a look at https://github.com/alexknvl/leibniz/blob/master/src/main/scala/leibniz/Instance.scala for a complete implementation that packages the instance with the value.

edmundnoble avatar Aug 01 '17 05:08 edmundnoble