I'm trying to play with HList's from Shapeless.
This is my first try:
trait Column[T] {
val name: String
}
case class CV[T](col: Column[T], value: T)
object CV {
object columnCombinator extends Poly2 {
implicit def algo[A] = at[(String, String, String), CV[A]] { case ((suffix, separator, sql), cv) ⇒
(suffix, separator, if (sql == "") cv.col.name+suffix else sql+separator+cv.col.name+suffix)
}
}
def combine[A <: HList](columns: A, suffix: String, separator: String = " and ")
(implicit l: LeftFolder[A, (String, String, String), columnCombinator.type]): String =
columns.foldLeft((suffix, separator, ""))(columnCombinator)._3
}
The problem is I don't know what foldLeft does return in this example.
I expect it to return (String, String, String), but the compiler tells me that returns l.Out. What is l.Out?
The source code is a little complicated to guess it.
There isn't much information in the web about this.
Some information I've consulted:
Shapeless Tests
Shapeless documentation
Your combine method returns what's called a "dependent method type", which just means that its return type depends on one of its arguments—in this case as a path-dependent type that includes l in its path.
In many cases the compiler will statically know something about the dependent return type, but in your example it doesn't. I'll try to explain why in a second, but first consider the following simpler example:
scala> trait Foo { type A; def a: A }
defined trait Foo
scala> def fooA(foo: Foo): foo.A = foo.a
fooA: (foo: Foo)foo.A
scala> fooA(new Foo { type A = String; def a = "I'm a StringFoo" })
res0: String = I'm a StringFoo
Here the inferred type of res0 is String, since the compiler statically knows that the A of the foo argument is String. We can't write either of the following, though:
scala> def fooA(foo: Foo): String = foo.a
<console>:12: error: type mismatch;
found : foo.A
required: String
def fooA(foo: Foo): String = foo.a
^
scala> def fooA(foo: Foo) = foo.a.substring
<console>:12: error: value substring is not a member of foo.A
def fooA(foo: Foo) = foo.a.substring
^
Because here the compiler doesn't statically know that foo.A is String.
Here's a more complex example:
sealed trait Baz {
type A
type B
def b: B
}
object Baz {
def makeBaz[T](t: T): Baz { type A = T; type B = T } = new Baz {
type A = T
type B = T
def b = t
}
}
Now we know that it's not possible to create a Baz with different types for A and B, but the compiler doesn't, so it won't accept the following:
scala> def bazB(baz: Baz { type A = String }): String = baz.b
<console>:13: error: type mismatch;
found : baz.B
required: String
def bazB(baz: Baz { type A = String }): String = baz.b
^
This is exactly what you're seeing. If we look at the code in shapeless.ops.hlist, we can convince ourselves that the LeftFolder we're creating here will have the same type for In and Out, but the compiler can't (or rather won't—it's a design decision) follow us in this reasoning, which means it won't let us treat l.Out as a tuple without more evidence.
Fortunately that evidence is pretty easy to provide thanks to LeftFolder.Aux, which is just an alias for LeftFolder with the Out type member as a fourth type parameter:
def combine[A <: HList](columns: A, suffix: String, separator: String = " and ")(
implicit l: LeftFolder.Aux[
A,
(String, String, String),
columnCombinator.type,
(String, String, String)
]
): String =
columns.foldLeft((suffix, separator, ""))(columnCombinator)._3
(You could also use the type member syntax with plain old LeftFolder in l's type, but that would make this signature even messier.)
The columns.foldLeft(...)(...) part still returns l.Out, but now the compiler statically knows that that's a tuple of strings.
After having read the complete answer from Travis, here is a little variation of his solution:
type CombineTuple = (String, String, String)
def combine[A <: HList](columns: A, suffix: String, separator: String = " and ")(
implicit l: LeftFolder[
A,
CombineTuple,
columnCombinator.type
]
): String =
columns.foldLeft((suffix, separator, ""))(columnCombinator).asInstanceof[CombineTuple]._3
In this way, the implicit signature is shorter, as it is needed in many methods that call this one.
UPDATED: As Travis has explained in comments, it is bestter to use LeftFolder.Aux.
Related
For example I have a class Value and a implicit function convert string to Value:
case class Value(v: String)
implicit def strToValue(s: String): Value = Value(s)
And here is a trait which has a method returns Value:
trait ReturnValue {
def f: Value
}
Because the implicit conversion exists, I can implement method f by just return a String literal:
object Obj1 extends ReturnValue {
override def f: Value = "123"
}
And of course return a variable of type String just works fine:
object Obj2 extends ReturnValue {
override def f: Value = {
val v = Some("123").getOrElse("234")
v
}
}
But when I trying to use the result of Option.getOrElse directly as the return value:
object Obj3 extends ReturnValue {
override def f: Value = Some("123").getOrElse("234") // Compilation error: type mismatch
}
A compilation error occurred:
Error:(23, 50) type mismatch;
found : java.io.Serializable
required: Entry.Value
override def f: Value = Some("123").getOrElse("234") // Compilation error: type mismatch
It seems that type inference here is failed. Type String is not inferred, and then the implicit conversion cannot be matched. (Full file is here)
I have tried other functions which have type parameter, such as "map", they all works perfectly.
Why is the Option.getOrElse so special that type inference failed here?
This variants leads to the same compile error, and probably shows how compiler deconstructs the expression:
object Obj3 extends ReturnValue {
override def f: Value = {
val v = Some("123") // is of type Some(String)
v.getOrElse("234": Value) // Compilation error: type mismatch
}
}
Same error can also be achieved without any traits, with following simple repro:
case class Value(v: String)
implicit def strToValue(s: String): Value = Value(s)
val vs = Some("123")
val v: Value = vs.getOrElse("234")
It seems the compiler applies the conversion to Value on the argument of getOrElse, instead of on its result. The fact is does can be confirmed with output with enabled scalacOptions in Compile ++= Seq("-Xprint-types", "-Xprint:typer") (cleaned a bit - deleted obviously unrelated annotations):
private[this] val v: Value =
vs.getOrElse{[B >: String](default: => B)B}[java.io.Serializable]{(default: => java.io.Serializable)java.io.Serializable}( strToValue{(s: String)Value}("234"{String("234")}){Value} ){
I think the inference works as follows:
vs type is known as Some[String]
getOrElse declaration is def getOrElse[B >: A](default: => B): B (A is String here)
compilers infers the B as Value, as this is the expected result type of the expression.
the most specific supertype of Value and String is Serializable
You can also note how it behaves when you remove the implicit conversion completely. The error for val v: Value = vs.getOrElse("234") is then: type mismatch;
found : String("234")
required: Value
This appears to be a compiler bug. Here's an example showing the odd behavior.
case class ValString(string: String)
object ValString {
implicit def string2ValString(string: String): ValString = ValString(string)
}
case class ValThing( one: ValString, two: ValString, three: ValString, four: ValString, five: ValString)
val opt = Option("aString")
val x = ValThing(
if(opt.isEmpty) "" else opt.get,
opt.fold("")(identity),
opt.orElse(Option("")).get,
opt.getOrElse(""): String,
ValString(opt.getOrElse(""))
)
The above all works, however
val x = ValThing( opt.getOrElse(""), .... )
fails because it interprets the output of the getOrElse as a Serializable
For example I have a class Value and a implicit function convert string to Value:
case class Value(v: String)
implicit def strToValue(s: String): Value = Value(s)
And here is a trait which has a method returns Value:
trait ReturnValue {
def f: Value
}
Because the implicit conversion exists, I can implement method f by just return a String literal:
object Obj1 extends ReturnValue {
override def f: Value = "123"
}
And of course return a variable of type String just works fine:
object Obj2 extends ReturnValue {
override def f: Value = {
val v = Some("123").getOrElse("234")
v
}
}
But when I trying to use the result of Option.getOrElse directly as the return value:
object Obj3 extends ReturnValue {
override def f: Value = Some("123").getOrElse("234") // Compilation error: type mismatch
}
A compilation error occurred:
Error:(23, 50) type mismatch;
found : java.io.Serializable
required: Entry.Value
override def f: Value = Some("123").getOrElse("234") // Compilation error: type mismatch
It seems that type inference here is failed. Type String is not inferred, and then the implicit conversion cannot be matched. (Full file is here)
I have tried other functions which have type parameter, such as "map", they all works perfectly.
Why is the Option.getOrElse so special that type inference failed here?
This variants leads to the same compile error, and probably shows how compiler deconstructs the expression:
object Obj3 extends ReturnValue {
override def f: Value = {
val v = Some("123") // is of type Some(String)
v.getOrElse("234": Value) // Compilation error: type mismatch
}
}
Same error can also be achieved without any traits, with following simple repro:
case class Value(v: String)
implicit def strToValue(s: String): Value = Value(s)
val vs = Some("123")
val v: Value = vs.getOrElse("234")
It seems the compiler applies the conversion to Value on the argument of getOrElse, instead of on its result. The fact is does can be confirmed with output with enabled scalacOptions in Compile ++= Seq("-Xprint-types", "-Xprint:typer") (cleaned a bit - deleted obviously unrelated annotations):
private[this] val v: Value =
vs.getOrElse{[B >: String](default: => B)B}[java.io.Serializable]{(default: => java.io.Serializable)java.io.Serializable}( strToValue{(s: String)Value}("234"{String("234")}){Value} ){
I think the inference works as follows:
vs type is known as Some[String]
getOrElse declaration is def getOrElse[B >: A](default: => B): B (A is String here)
compilers infers the B as Value, as this is the expected result type of the expression.
the most specific supertype of Value and String is Serializable
You can also note how it behaves when you remove the implicit conversion completely. The error for val v: Value = vs.getOrElse("234") is then: type mismatch;
found : String("234")
required: Value
This appears to be a compiler bug. Here's an example showing the odd behavior.
case class ValString(string: String)
object ValString {
implicit def string2ValString(string: String): ValString = ValString(string)
}
case class ValThing( one: ValString, two: ValString, three: ValString, four: ValString, five: ValString)
val opt = Option("aString")
val x = ValThing(
if(opt.isEmpty) "" else opt.get,
opt.fold("")(identity),
opt.orElse(Option("")).get,
opt.getOrElse(""): String,
ValString(opt.getOrElse(""))
)
The above all works, however
val x = ValThing( opt.getOrElse(""), .... )
fails because it interprets the output of the getOrElse as a Serializable
I'm working on a port of servant-server to Scala. The idea is to use typeclass resolution to inductively build functions that can handle requests. I'm running into some weird inference issues I can't quite figure out.
object Servant {
class :>[Path, A]
trait HasServer[A] {
type ServerT
def route(a: ServerT): String
}
implicit val unitServer = new HasServer[Unit] {
type ServerT = String
def route(str: ServerT): String = str
}
implicit def subServer[A, Sub](implicit sub: HasServer[Sub]) = new HasServer[A :> Sub] {
type ServerT = A => sub.ServerT
def route(handler: ServerT): String = "handler"
}
}
With the above, the following fails to compile:
val foo = implicitly[HasServer[Int :> Unit]]
implicitly[=:=[Int => String, foo.ServerT]]
The error is:
servant.scala:33: error:
Cannot prove that Int => String =:= Main.$anon.Servant.foo.ServerT.
However, it will compile if I instantiate HasServer[Int :> Unit] directly, via:
val foo = new HasServer[Int :> Unit] {
type ServerT = Int => unitServer.ServerT
def route(handler: ServerT): String = handler(10)
}
How can I get this to compile? Thanks!
The problem is all in the definition of implicitly ...
def implicitly[T](implicit e: T) = e
implicitly[T] will only ever give you a value which is typed as T, never anything more precise. In the case above, that's HasServer[Int :> Unit] which, crucially, leaves the member type ServerT unconstrained.
This is commonly worked around by defining a per type class companion object apply method which preserves the desired refinement, eg.,
object HasServer {
def apply[T](implicit hs: HasServer[T]):
HasServer[T] { type ServerT = hs.ServerT } = hs
}
the result type here is a little unwieldy, so it's also common to combine this with the "Aux" pattern,
object HasServer {
type Aux[T, S] = HasServer[T] { type ServerT = S }
def apply[T](implicit hs: HasServer[T]): Aux[T, hs.ServerT] = hs
}
which will probably come in handy elsewhere in any case.
We can see the difference this makes to the inferred types on the REPL,
scala> implicitly[HasServer[Int :> Unit]]
res0: Servant.HasServer[Servant.:>[Int,Unit]] = ...
scala> HasServer[Int :> Unit]
res1: Servant.HasServer[Servant.:>[Int,Unit]]{type ServerT = Int => String} = ...
This refinement will be inferred as the type of a val definition, so now you'll get the desired result,
scala> val foo = HasServer[Int :> Unit]
foo: Servant.HasServer[Servant.:>[Int,Unit]]{type ServerT = Int => String} = ...
scala> implicitly[=:=[Int => String, foo.ServerT]]
res2: =:=[Int => String,foo.ServerT] = <function1>
There are a number of ways that the definition of implicitly could be improved to avoid this problem. The following is the most straightforward for reference types,
def implicitly[T <: AnyRef](implicit t: T): t.type = t
and if literal types are enabled we could removed the <: AnyRef bound and define it for all types,
def implicitly[T](implicit t: T): t.type = t
shapeless provides a the[T] operator which behaves similarly to the latter via a macro.
Given the following piece of code:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A)(implicit dummy: DummyImplicit) = Attribute(name, value)
def apply(value: String) = Attribute[A](name, value)
}
The Scala compiler complains with "ambiguous reference to overloaded definition" when it sees the values hereafter:
1| val FooAttr = Attr[String]("foo")
2| val catch22 = FooAttr("bar")
Line 1: My intent is it to pass to the factory "Attr" producing "Attributes" the value type "String" as well as the name "foo" for all the attributes it ever produces.
Line 2: Using the previously configured attribute factory I am actually producing an attribute named "foo" with the value "bar" of type "String".
My conclusion: Because the parameterized type "A" for this factory object is "String" the Scala compiler deduces the same parameter signatures of method "apply" being "(value: String)" which are ambiguous. Therefore I tried to make a difference in signature by adding an implicit parameter list.
After having read an article about type erasure and DummyImplicit and consulting the Scala reference section "7.2 Implicit parameters" I thought "(implicit dummy: DummyImplicit)" would do the trick.
For the moment my solution is to have the minimal wrapper:
final case class Txt(str: String) {
override def toString = str
}
Given that an implicit value of type "Str To Txt", i.e. a suitable conversion function, could be found, the second line from above compiles, i.e.:
2| val catch22 = FooAttr("bar")
It seems I was thinking too complicated. Instead to overload the apply method with a parameter list of (value: String), I simply got rid of it. The version that lives up to my full expectations now looks like:
final case class Attr[A](name: String)(implicit conv: String To A) {
def apply(value: A) = Attribute(name, value)
}
How about this?
case class Attribute[A](name: String, value: A)
case class AttrBuilder[A](name: String)(implicit conv: String => A) {
def apply[B](value: B)(implicit conv: B => A) = Attribute(name, conv(value))
}
val bldr = new AttrBuilder[String]("MyAttrs")
bldr("hello") // Attribute(MyAttrs, hello)
implicit def int2string(x: Int) = x.toString
bldr(2) // Attribute(MyAttrs, 2), using int2string implicit
bldr(false) // fails; cannot find implicit Boolean => String
The attribute builder bldr will take any value of type B that's convertable to A == String, including strings themselves (the implicit conversion Predef.conforms is used in that case).
I have seen a function named implicitly used in Scala examples. What is it, and how is it used?
Example here:
scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: type mismatch;
found : Int(1)
required: List[?]
foo(1)
^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:8: error: could not find implicit value for evidence parameter of type
Foo[Double]
foo(List(1.0))
^
Note that we have to write implicitly[Foo[A]].apply(x) since the compiler thinks that implicitly[Foo[A]](x) means that we call implicitly with parameters.
Also see How to investigate objects/types/etc. from Scala REPL? and Where does Scala look for implicits?
implicitly is avaliable in Scala 2.8 and is defined in Predef as:
def implicitly[T](implicit e: T): T = e
It is commonly used to check if an implicit value of type T is available and return it if such is the case.
Simple example from retronym's presentation:
scala> implicit val a = "test" // define an implicit value of type String
a: java.lang.String = test
scala> val b = implicitly[String] // search for an implicit value of type String and assign it to b
b: String = test
scala> val c = implicitly[Int] // search for an implicit value of type Int and assign it to c
<console>:6: error: could not find implicit value for parameter e: Int
val c = implicitly[Int]
^
Here are a few reasons to use the delightfully simple method implicitly.
To understand/troubleshoot Implicit Views
An Implicit View can be triggered when the prefix of a selection (consider for example, the.prefix.selection(args) does not contain a member selection that is applicable to args (even after trying to convert args with Implicit Views). In this case, the compiler looks for implicit members, locally defined in the current or enclosing scopes, inherited, or imported, that are either Functions from the type of that the.prefix to a type with selection defined, or equivalent implicit methods.
scala> 1.min(2) // Int doesn't have min defined, where did that come from?
res21: Int = 1
scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>
scala> res22(1) //
res23: AnyRef{def min(i: Int): Int} = 1
scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt
Implicit Views can also be triggered when an expression does not conform to the Expected Type, as below:
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Here the compiler looks for this function:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
Accessing an Implicit Parameter Introduced by a Context Bound
Implicit parameters are arguably a more important feature of Scala than Implicit Views. They support the type class pattern. The standard library uses this in a few places -- see scala.Ordering and how it is used in SeqLike#sorted. Implicit Parameters are also used to pass Array manifests, and CanBuildFrom instances.
Scala 2.8 allows a shorthand syntax for implicit parameters, called Context Bounds. Briefly, a method with a type parameter A that requires an implicit parameter of type M[A]:
def foo[A](implicit ma: M[A])
can be rewritten as:
def foo[A: M]
But what's the point of passing the implicit parameter but not naming it? How can this be useful when implementing the method foo?
Often, the implicit parameter need not be referred to directly, it will be tunneled through as an implicit argument to another method that is called. If it is needed, you can still retain the terse method signature with the Context Bound, and call implicitly to materialize the value:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Passing a subset of implicit parameters explicitly
Suppose you are calling a method that pretty prints a person, using a type class based approach:
trait Show[T] { def show(t: T): String }
object Show {
implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }
def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}
case class Person(name: String, age: Int)
object Person {
implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
}
}
val p = Person("bob", 25)
implicitly[Show[Person]].show(p)
What if we want to change the way that the name is output? We can explicitly call PersonShow, explicitly pass an alternative Show[String], but we want the compiler to pass the Show[Int].
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
Starting Scala 3 implicitly has been replaced with improved summon which has the advantage of being able to return a more precise type than asked for
The summon method corresponds to implicitly in Scala 2. It is
precisely the same as the the method in Shapeless. The difference
between summon (or the) and implicitly is that summon can return a
more precise type than the type that was asked for.
For example given the following type
trait F[In]:
type Out
def f(v: Int): Out
given F[Int] with
type Out = String
def f(v: Int): String = v.toString
implicitly method would summon a term with erased type member Out
scala> implicitly[F[Int]]
val res5: F[Int] = given_F_Int$#7d0e5fbb
scala> implicitly[res5.Out =:= String]
1 |implicitly[res5.Out =:= String]
| ^
| Cannot prove that res5.Out =:= String.
scala> val x: res5.Out = ""
1 |val x: res5.Out = ""
| ^^
| Found: ("" : String)
| Required: res5.Out
In order to recover the type member we would have to refer to it explicitly which defeats the purpose of having the type member instead of type parameter
scala> implicitly[F[Int] { type Out = String }]
val res6: F[Int]{Out = String} = given_F_Int$#7d0e5fbb
scala> implicitly[res6.Out =:= String]
val res7: res6.Out =:= String = generalized constraint
However summon defined as
def summon[T](using inline x: T): x.type = x
does not suffer from this problem
scala> summon[F[Int]]
val res8: given_F_Int.type = given_F_Int$#7d0e5fbb
scala> summon[res8.Out =:= String]
val res9: String =:= String = generalized constraint
scala> val x: res8.Out = ""
val x: res8.Out = ""
where we see type member type Out = String did not get erased even though we only asked for F[Int] and not F[Int] { type Out = String }. This can prove particularly relevant when chaining dependently typed functions:
The type summoned by implicitly has no Out type member. For this
reason, we should avoid implicitly when working with dependently typed
functions.
A "teach you to fish" answer is to use the alphabetic member index currently available in the Scaladoc nightlies. The letters (and the #, for non-alphabetic names) at the top of the package / class pane are links to the index for member names beginning with that letter (across all classes). If you choose I, e.g., you'll find the implicitly entry with one occurrence, in Predef, which you can visit from the link there.