Decoding Shapeless Tagged Types - scala

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.

Related

Decoding Case Class w/ Tagged Type

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)

Build List of Foo's with Specific Value at Compile-Time

Given:
case class Foo(x: BigDecimal)
I'd like to, at compile-time, build a List[Foo] where each Foo must have a BigDecimal value of 5.
So, I'd expect the following code to compile:
type Foo5Only = ???
val foos5: List[Foo5Only] = List(Foo(5), Foo(5))
But, I'd expect the following to fail to compile:
val bad: List[Foo5Only] = List(Foo(42))
I'm speculating that a shapeless Singleton type might be useful, but I don't actually understand it.
Note - I'm not interested, for this question, in an answer that results in using Either or Option.
As well as using shapeless' Nat type you could also use singleton types. Unfortunately Scala's built-in List type has covariance which gets in the way of type safety, but using a simple hand-crafted list type seems to work:
import shapeless.syntax.singleton._
sealed trait Lst[T]
case class Nil[T]() extends Lst[T]
case class Cons[T](head : T, tail : Lst[T]) extends Lst[T]
def list[T](t : T) : Lst[T] = {
Cons(t, Nil())
}
// OK
val foos5 = Cons(5.narrow, list(5.narrow))
// Compile-time type mismatch error.
val foos6 = Cons(42.narrow, list(5.narrow))
You might be able to elide the narrows with some macro-magic, but that's beyond my ability.

Scalaz: how does `scalaz.syntax.applicative._` works its magic

This question is related to this one, where I was trying to understand how to use the reader monad in Scala.
In the answer the autor uses the following code for getting an instance of ReaderInt[String]:
import scalaz.syntax.applicative._
val alwaysHello2: ReaderInt[String] = "hello".point[ReaderInt]
Which mechanisms does Scala use to resolve the type of the expression "hello".point[ReaderInt] so that it uses the right point function?
A good first step any time you're trying to figure out something like this is to use the reflection API to desugar the expression:
scala> import scalaz.Reader, scalaz.syntax.applicative._
import scalaz.Reader
import scalaz.syntax.applicative._
scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}
scala> type ReaderInt[A] = Reader[Int, A]
defined type alias ReaderInt
scala> showCode(reify("hello".point[ReaderInt]).tree)
res0: String = `package`.applicative.ApplicativeIdV("hello").point[$read.ReaderInt](Kleisli.kleisliIdMonadReader)
(You generally don't want to use scala.reflect.runtime in real code, but it's extremely handy for investigations like this.)
When the compiler sees you trying to call .point[ReaderInt] on a type that doesn't have a point method—in this case String—it starts looking for implicit conversions that would convert a String into a type that does have a matching point method (this is called "enrichment" in Scala). We can see from the output of showCode that the implicit conversion it finds is a method called ApplicativeIdV in the applicative syntax object.
It then applies this conversion to the String, resulting in a value of type ApplicativeIdV[String]. This type's point method looks like this:
def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)
Which is syntactic sugar for something like this:
def point[F[_]](implicit F: Applicative[F]): F[A] = F.point(self)
So the next thing it needs to do is find an Applicative instance for F. In your case you've explicitly specified that F is ReaderInt. It resolves the alias to Reader[Int, _], which is itself an alias for Kleisli[Id.Id, Int, _], and starts looking for an instance.
One of the first places it looks will be the Kleisli companion object, since it wants an implicit value of a type that includes Kleisli, and in fact showCode tells us that the one it finds is Kleisli.kleisliIdMonadReader. At that point it's done, and we get the ReaderInt[String] we wanted.
I wanted to update the former answer, but since you created separate question, I put it here.
scalaz.syntax
Let's consider the point example, and you can apply the same reasoning for other methods.
point (or haskell's return) or pure(just a type alias) belongs to Applicative trait. If you want to put something inside some F, you need at least Applicative instance for this F.
Usually, you will provide it implicitly with imports, but you can specify it explicitly as well.
In example from the first question, I assigned it to val
implicit val KA = scalaz.Kleisli.kleisliIdApplicative[Int]
because scala was not able to figure out the corresponding Int type for this applicative. In other words, it did not know Applicative for which Reader to bring in. (though sometimes compiler can figure it out)
For the Applicatives with one type parameter, we can bring implicit instances in just by using import
import scalaz.std.option.optionInstance
import scalaz.std.list.listInstance
etc...
Okay, you have the instance. Now you need to invoke point on it.
You have few options:
1. Access method directly:
scalaz.std.option.optionInstance.point("hello")
KA.pure("hello")
2. Explicitly pull it from implicit context:
Applicative[Option].point("hello")
If you look into Applicative object, you would see
object Applicative {
#inline def apply[F[_]](implicit F: Applicative[F]): Applicative[F] = F
}
Implementation of apply, is only returning the corresponding Applicative[F] instance for some type F.
So Applicative[Option].point("hello") is converted to
Applicative[Option].apply(scalaz.std.option.optionInstance)
which in the end is just optionInstance
3. Use syntax
import scalaz.syntax.applicative._
brings this method into implicit scope:
implicit def ApplicativeIdV[A](v: => A) = new ApplicativeIdV[A] {
val nv = Need(v)
def self = nv.value
}
trait ApplicativeIdV[A] extends Ops[A] {
def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)
def pure[F[_] : Applicative]: F[A] = Applicative[F].point(self)
def η[F[_] : Applicative]: F[A] = Applicative[F].point(self)
} ////
So then, whenever you try to invoke point on a String
"hello".point[Option]
compiler realizes, that String does not have the method point and begins to look through implicits, how it can get something which has point, from String.
It finds, that it can convert String to ApplicativeIdV[String], which indeed has method point:
def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)
So in the end - your call desugares to
new ApplicativeIdV[Option]("hello")
More or less all typeclasses in scalaz are working the same way.
For sequence, the implementation is
def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]] =
traverse(fga)(ga => ga)
This colon after G means, that Applicative[G] should be provided implicitly.
It is essentialy the same as:
def sequence[G[_], A](fga: F[G[A]])(implicit ev: Applicative[G[_]]): G[F[A]] =
traverse(fga)(ga => ga)
So all you need is the Applicative[G], and Traverse[F].
import scalaz.std.list.listInstance
import scalaz.std.option.optionInstance
Traverse[List].sequence[Option, String](Option("hello"))

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 test type conformance of higher-kinded types in Scala

I am trying to test whether two "containers" use the same higher-kinded type. Look at the following code:
import scala.reflect.runtime.universe._
class Funct[A[_],B]
class Foo[A : TypeTag](x: A) {
def test[B[_]](implicit wt: WeakTypeTag[B[_]]) =
println(typeOf[A] <:< weakTypeOf[Funct[B,_]])
def print[B[_]](implicit wt: WeakTypeTag[B[_]]) = {
println(typeOf[A])
println(weakTypeOf[B[_]])
}
}
val x = new Foo(new Funct[Option,Int])
x.test[Option]
x.print[Option]
The output is:
false
Test.Funct[Option,Int]
scala.Option[_]
However, I expect the conformance test to succeed. What am I doing wrong? How can I test for higher-kinded types?
Clarification
In my case, the values I am testing (the x: A in the example) come in a List[c.Expr[Any]] in a Macro. So any solution relying on static resolution (as the one I have given), will not solve my problem.
It's the mixup between underscores used in type parameter definitions and elsewhere. The underscore in TypeTag[B[_]] means an existential type, hence you get a tag not for B, but for an existential wrapper over it, which is pretty much useless without manual postprocessing.
Consequently typeOf[Funct[B, _]] that needs a tag for raw B can't make use of the tag for the wrapper and gets upset. By getting upset I mean it refuses to splice the tag in scope and fails with a compilation error. If you use weakTypeOf instead, then that one will succeed, but it will generate stubs for everything it couldn't splice, making the result useless for subtyping checks.
Looks like in this case we really hit the limits of Scala in the sense that there's no way for us to refer to raw B in WeakTypeTag[B], because we don't have kind polymorphism in Scala. Hopefully something like DOT will save us from this inconvenience, but in the meanwhile you can use this workaround (it's not pretty, but I haven't been able to come up with a simpler approach).
import scala.reflect.runtime.universe._
object Test extends App {
class Foo[B[_], T]
// NOTE: ideally we'd be able to write this, but since it's not valid Scala
// we have to work around by using an existential type
// def test[B[_]](implicit tt: WeakTypeTag[B]) = weakTypeOf[Foo[B, _]]
def test[B[_]](implicit tt: WeakTypeTag[B[_]]) = {
val ExistentialType(_, TypeRef(pre, sym, _)) = tt.tpe
// attempt #1: just compose the type manually
// but what do we put there instead of question marks?!
// appliedType(typeOf[Foo], List(TypeRef(pre, sym, Nil), ???))
// attempt #2: reify a template and then manually replace the stubs
val template = typeOf[Foo[Hack, _]]
val result = template.substituteSymbols(List(typeOf[Hack[_]].typeSymbol), List(sym))
println(result)
}
test[Option]
}
// has to be top-level, otherwise the substituion magic won't work
class Hack[T]
An astute reader will notice that I used WeakTypeTag in the signature of foo, even though I should be able to use TypeTag. After all, we call foo on an Option which is a well-behaved type, in the sense that it doesn't involve unresolved type parameters or local classes that pose problems for TypeTags. Unfortunately, it's not that simple because of https://issues.scala-lang.org/browse/SI-7686, so we're forced to use a weak tag even though we shouldn't need to.
The following is an answer that works for the example I have given (and might help others), but does not apply to my (non-simplified) case.
Stealing from #pedrofurla's hint, and using type-classes:
trait ConfTest[A,B] {
def conform: Boolean
}
trait LowPrioConfTest {
implicit def ctF[A,B] = new ConfTest[A,B] { val conform = false }
}
object ConfTest extends LowPrioConfTest {
implicit def ctT[A,B](implicit ev: A <:< B) =
new ConfTest[A,B] { val conform = true }
}
And add this to Foo:
def imp[B[_]](implicit ct: ConfTest[A,Funct[B,_]]) =
println(ct.conform)
Now:
x.imp[Option] // --> true
x.imp[List] // --> false