Decoding Case Class w/ Tagged Type - scala

Given:
Given the following on Ammonite:
# import $ivy.`io.circe::circe-core:0.9.0`
# import $ivy.`io.circe::circe-generic:0.9.0`
# import $ivy.`com.chuusai::shapeless:2.3.3`
# import shapeless.tag
import shapeless.tag
# trait Foo
defined trait Foo
# import io.circe._, io.circe.generic.semiauto._
import io.circe._, io.circe.generic.semiauto._
# import shapeless.tag.##
import shapeless.tag.##
# implicit def taggedTypeDecoder[A, B](implicit ev: Decoder[A]): Decoder[A ## B] =
ev.map(tag[B][A](_))
defined function taggedTypeDecoder
Given a Foo:
# case class F(x: String ## Foo)
defined class F
I can summon an Decoder[String ## Foo]:
# Decoder[String ## Foo]
res17: Decoder[String ## Foo] = io.circe.Decoder$$anon$21#16b32e49
But not a F:
# deriveDecoder[F]
cmd18.sc:1: could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[ammonite.$sess.cmd16.F]
val res18 = deriveDecoder[F]
^
Compilation Failed
How can I get a Decoder[F]?

This is a bug in shapeless' Lazy - milessabin/shapeless#309
I have a PR that makes your example compile - milessabin/shapeless#797 (I checked with publishLocal)
Basically the problem in Lazy is that it expands type aliases too eagerly (A ## B is a type alias for A with Tagged[B]) which in turn triggers a Scala bug - scala/bug#10506
The Scala bug doesn't have a clear solution in sight. It's another incarnation of the subtyping vs parametric polymorphism problem that complicates type inference. The gist of it is that Scala has to perform subtype checking and type inference at the same time. But when we put some type variables like A and B in a refined type like A with Tagged[B] (actually circe ends up looking for a FieldType[K, A with Tagged[B]] where FieldType is yet another type alias hiding a refined type), subtyping has to be checked for each component individually. This means that the order in which we choose to check the components determines how the type variables A and B will be constrained. In some cases they end up over- or under-constrained and cannot be inferred correctly.
Apropo, the shapeless tests show a workaround, but I don't think it applies to circe, because it's using some kind of macro rather than doing vanilla typeclass derivation.
Long story short you can:
Wait for a shapeless (please upvote #797) and subsequent circe release
Not use tagged types =/
Try to use a different encoding without refined or structural types - maybe alexknvl/newtypes? (I haven't tried)

Related

Decoding Shapeless Tagged Types

Given the following on Ammonite:
# import $ivy.`io.circe::circe-core:0.9.0`
# import $ivy.`io.circe::circe-generic:0.9.0`
# import $ivy.`com.chuusai::shapeless:2.3.3`
# import shapeless.tag
import shapeless.tag
# trait Foo
defined trait Foo
# import io.circe._, io.circe.generic.semiauto._
import io.circe._, io.circe.generic.semiauto._
# import shapeless.tag.##
import shapeless.tag.##
Then, I attempted to define a generic tagged type decoder:
# implicit def taggedTypeDecoder[A, B](implicit ev: Decoder[A]): Decoder[A ## B] =
ev.map(tag[B][A](_))
defined function taggedTypeDecoder
It works when explicitly spelling out String ## Foo:
# val x: String ## Foo = tag[Foo][String]("foo")
x: String ## Foo = "foo"
# implicitly[Decoder[String ## Foo]]
res10: Decoder[String ## Foo] = io.circe.Decoder$$anon$21#2b17bb37
But, when defining a type alias:
# type FooTypeAlias = String ## Foo
defined type FooTypeAlias
It's not compiling:
# implicitly[Decoder[FooTypeAlias]]
cmd12.sc:1: diverging implicit expansion for type io.circe.Decoder[ammonite.$sess.cmd11.FooTypeAlias]
starting with method decodeTraversable in object Decoder
val res12 = implicitly[Decoder[FooTypeAlias]]
^
Compilation Failed
Why is that? Is there a known "fix?"
Lucky you, to hit two compiler bugs in the same day. This one is scala/bug#8740. The good? news is that there is a partial fix waiting around in this comment for someone to step up and make a PR (maybe this is you). I believe it's partial because it looks like it will work for a specific tag but not for a generic one (I'm not 100% sure).
The reason why you see a diverging implicit expansion is really funny. The compiler can either expand all aliases in one step (essentially going from FooTypeAlias |= String with Tagged[Foo]) or not expand anything. So when it compares String ## Foo and A ## B it doesn't expand, because they match as is. But when it compares FooTypeAlias and A ## B it expands both fully and it ends up in a situation where it has to compare refined types one of which contains type variables (see my answer to your other related question). Here our carefully crafted abstractions break down again and the order of constraints starts to matter. You as the programmer, looking at A with Tagged[B] <:< String with Tagged[Foo] know that the best match is A =:= String and B =:= Foo. However Scala will first compare A <:< String and A <:< Tagged[Foo] and it concludes that A <:< Tagged[Foo] with String (yes, in reverse) which leaves Nothing for B. But wait, we need an implicit Decoder[A]! - which sends us in a loop. So A got over-constrained and B got under-constrained.
Edit: It seems to work if we make ## abstract in order to prevent the compiler from dealiasing: milessabin/shapeless#807. But now it boxes and I can't make arrays work.

Can I use a class defined in a `ToolBox` as a type parameter of `typeOf[]`?

I'd like to experiment with the use of a dynamic data model with a reflective library that uses typeOf[].
I've defined a class at runtime with a Scala reflection ToolBox in 2.11:
import scala.tools.reflect.ToolBox
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{ currentMirror => cm }
def cdef() = q"case class C(v: String)"
val tb = cm.mkToolBox()
val csym = tb.define(cdef())
def newc(csym: Symbol) = q"""new ${csym}("hi")"""
val obj = tb.eval(newc(csym))
I'm able to circumvent the typeOf[] call by entering Scala reflection via the ClassSymbol instead, but that requires modifying a library over which I have no immediate control.
Is there any way that I can use it as a type parameter in a library whose entry point is typeOf[]?
I've tried:
The only way I found to go from a value to something that I could use in the type position was use Java reflection to invoke the companion class' apply method and call .type on the result:
val method_apply = obj.getClass.getMethod("apply", "".getClass)
val typeTemplate = method_apply.invoke(obj, "hello")
type MyType = typeTemplate.type
(Keeping with the naming scheme of #xeno_by and #travisbrown 's menagerie of odd types, I might call this "Frankenstein's Type", because it is made from parts, given life at the wrong time, not quite a substitute for the original, and given that this is all happening at runtime, should probably be burned with fire.)
This type alias works as a type parameter is some cases. But in the case of typeOf[MyType], the the compiler makes a TypeTag before the runtime type is defined, so typeOf[MyType] returns a type member that doesn't correspond to the runtime type/class (e.g. TypeTag[package.Example.MyType] instead of TypeTag[package.C])
Should I expect the ToolBox to have generated a TypeTag, and if so, how do I use it?
If I have to make a TypeTag at runtime, this question shows me how, but then how do I attach it to whatever I use as a type parameter?
Thanks for any ideas,
-Julian

Why do we have to explicitly import implicit conversions having implicit parameters from companion objects? Strange.

Let's consider this code:
class A
object A{
implicit def A2Int(implicit a:A)=1
implicit def A2String(a:A)="Hello"
}
object Run extends App{
implicit val a: A =new A
import A.A2Int
// without this import this code does not compile, why ?
// why is no import needed for A2String then ?
def iWantInt(implicit i:Int)=println(i)
def iWantString(implicit s:String)=println(s)
iWantInt
iWantString(a)
}
It runs and prints:
1
Hello
Now, if we comment out the line
import A.A2Int
then we get a compilation error:
With the line commented out, why Scala cannot find A.A2String if it can find A.A2Int ?
How can this problem be fixed ?
Thanks for reading.
The difference is that when you do iWantString(a), the compiler gets some starting point to work from: you are explicitly passing a, which the compiler knows is of type A.
Given that iWantString takes a String and not an A, the compiler will search for an implicit conversion from A to String in order to insert it and make the call succeed.
Implicit lookup rules state that the compiler must look (among other places) in the companion object of class A because type A is the source type of the conversion.
This is where it finds the implicit conversion A2String.
What you must get from this is that it is only because you passed an instance of A that the compiler knew to look for implicit conversions into the companion object of A.
When you just do iWantInt, the compiler has no reason to look into A, so it won't find your method A2Int (and as no other method/value in scope provides an implicit value of type Int, compilation then fails).
For more information about implicit lookup rules, see the
See the scala specification at http://www.scala-lang.org/docu/files/ScalaReference.pdf (chapter 7.2). Here's the most relevant excerpt:
The implicit scope of a type T consists of all companion modules (§5.4) of classes
that are associated with the implicit parameter’s type.

How to make scalaz.Tagged work with class class primitive attributes?

Consider the following example:
import scalaz._
object TaggedExample {
sealed trait Test
def Test[A](a: A): A ## Test = Tag[A, Test](a)
}
case class TaggedAttribute(l: Long ## TaggedExample.Test)
It will fail to compile with next reason:
scalac: type mismatch;
found : Double
required: AnyRef
Note: an implicit exists from scala.Double => java.lang.Double, but
methods inherited from Object are rendered ambiguous. This is to avoid
a blanket implicit which would convert any scala.Double to any AnyRef.
You may wish to use a type ascription: `x: java.lang.Double`.
To my understanding, it is happens due to some details in case class compiler code generation (because simple def test(l: Long ## TaggedExample.Test) = l compiles just fine).
If we change case class definition to
case class TaggedAttribute(l: java.lang.Long ## TaggedExample.Test)
compilation will succeed.
The question is: Is there a way to avoid this scalac error without changing type of l to java.lang.Long (which, in turn, will allow l to be null etc.)?
Update
Found this Tagged type : type mismatch question and answer to it right after posting, but still: may be there is a way to avoid use of java.lang.* box types.
Know bug: Compiler error when using tagged types and case classes
Workaround: use box types.

How to construct wildcard type in Scala macro?

I am unable to find out how to programatically construct existential types in Scala macros.
For example, let's assume that I have a ClassSymbol that represents a class C[T] that has one type parameter.
Now, how do I programatically construct the type C[_ <: java.lang.Number] ?
In particular, I have no idea how to use the ExistentialType constructor object. Looking at its signature:
def apply(quantified: List[Symbol], underlying: Type): ExistentialType
What do I pass as quantified?
From what I understand, you need to create quantified symbols yourself, setting their signatures manually. Here's an abridged and adapted version of what -Ymacro-debug-lite printed when I compiled typeOf[C[_ <: Number]]. Maybe Jason or Paul know a shortcut that avoids creating symbols manually, but I'm not sure the one exists in the public API.
class C[T]
object Test extends App {
import scala.reflect.runtime.universe._
val c = typeOf[C[_]].typeSymbol
val targ = build.newNestedSymbol(NoSymbol, newTypeName("_$1"), NoPosition, build.flagsFromBits(34359738384L), false)
build.setTypeSignature(targ, TypeBounds(typeOf[Nothing], typeOf[Number]))
println(ExistentialType(List(targ), TypeRef(c.owner.asClass.thisPrefix, c, List(TypeRef(NoPrefix, targ, Nil)))))
}