What is the difference between following two declarations of sum functions?
def sum[A](xs:List[A]) = .....
def sum[A <: List[A]](xs:A) = ....
EDIT:
To elaborate more....
Lets say I want to write a method head on List.
I can write head as follow:
def head[A](xs:List[A]) = xs(0)
or else we can write
def head[A <: List[A]] (xs:A) = xs(0)
Which one to prefer and when?
Note: one difference I figured out that implicit conversions are not applied for second one
The first one takes a List[A] as parameter, the second one some A that is a subtype of List[A]. Consider the following example:
scala> trait Foo[A <: Foo[A]]
defined trait Foo
scala> class Bar extends Foo[Bar]
defined class Bar
The recursive type parameter on Foo can be useful, when you want to define a method in the trait that takes or returns the type of the subclass:
trait Foo[A <: Foo[A]] {
def f: A
}
class Bar extends Foo[Bar] {
def f: Bar = new Bar
}
class Baz extends Foo[Baz] {
def f: Baz = new Baz
}
I don't know how your specific example should work, because I don't know how you would sum on that type.
Related
I have tried to create a minimal example, x doesn't compile in the code below:
sealed trait Foo
case object FooOne extends Foo
sealed trait Bar[T] {
type foo <: Foo
}
object Bar {
implicit case object BarOne extends Bar[Int] {
type foo = FooOne.type
}
}
case class Quk[B: Bar](b: B)
sealed trait Baz[F <: Foo]
case object BazOne extends Baz[FooOne.type]
case class Bat[B: Bar, F <: Foo](r: Quk[B], z: Baz[F])(implicit ev: Bar[B]#foo =:= F)
object Bat {
val x = Bat(Quk(1), BazOne) // Compilation error here!
}
The error I'm getting (in eclipse) is:
Cannot prove that com.muhuk.Example.Bar[Int]#foo =:= com.muhuk.Example.FooOne.type.
not enough arguments for method apply: (implicit evidence$2: com.muhuk.Example.Bar[Int], implicit ev: =:=[com.muhuk.Example.Bar[Int]#foo,com.muhuk.Example.FooOne.type])com.muhuk.Example.Bat[Int,com.muhuk.Example.FooOne.type] in object Bat. Unspecified value parameter ev.
Foo doesn't depend on anything. Bar & Baz depend on Foo but they don't know about each other, except in the context of Bat.
How can I get Bat's constructor to ensure its Quk parameter and Baz parameter have both the same Foo type?
I am using Scala 2.11.8.
You could use the Aux type alias trick for Bar and its dependant type foo :
object Bar {
type Aux[T, F] = Bar[T] { type foo = F }
// BarOne ...
}
Now you can define Bat as follows :
case class Bat[B, F <: Foo](r: Quk[B], z: Baz[F])(implicit bar: Bar.Aux[B, F])
Your example now compiles :
val x = Bat(Quk(1), BazOne)
// x: Bat[Int,FooOne.type] = Bat(Quk(1),BazOne)
I have the simplified situation:
abstract sealed trait Top
class A[T] extends Top
class B[T] extends Top
class Typeclass[T]
implicit def a[T] = new Typeclass[A[T]]
implicit def b[T] = new Typeclass[B[T]]
Now I have a Map[String, Top] and want to use an operation on all values in the map that require the presence of an instance of Typeclass to be available in the context. This will not compile as the concrete types of the values in the map are not visible from its type and I can therefore not set a context bound for them.
Is there a way to tell the compiler that in fact there will always be an instance available? In this example this is given as there are implicit functions to generate those instances for every concrete subtype of Top.
Or is the only solution to use a HList and recurse over its type requiring all the instances to be in context?
I recommend using some variation on this adaptation of Oleg's Existentials as universals in this sort of situation ... pack the the type class instance along with the value it's the instance for,
abstract sealed trait Top
class A[T] extends Top
class B[T] extends Top
class Typeclass[T]
implicit def a[T] = new Typeclass[A[T]]
implicit def b[T] = new Typeclass[B[T]]
trait Pack {
type T <: Top
val top: T
implicit val tc: Typeclass[T]
}
object Pack {
def apply[T0 <: Top](t0: T0)(implicit tc0: Typeclass[T0]): Pack =
new Pack { type T = T0 ; val top = t0 ; val tc = tc0 }
}
val m = Map("a" -> Pack(new A[Int]), "b" -> Pack(new B[Double]))
def foo[T: Typeclass](t: T): Unit = ()
def bar(m: Map[String, Pack], k: String): Unit =
m.get(k).map { pack =>
import pack._ // imports T, top and implicit tc
foo(top) // instance available for call of foo
}
bar(m, "a")
As discussed in comment it would be more convenient to have the typeclass defined on Top, and it might be done with pattern matching.
supposing part of the definition of the typeclass is
def f[T](t: T): FResult[T],
and you have the corresponding implentations
def fOnA[T](t: A[T]): FResult[A[T]] = ...
def fOnB[T](t: B[T]): FResult[B[T]] = ...
Then you can define
def fOnT(t: Top) : FResult[Top] = t match {
case a: A[_] => fOnA(a)
// provided an FResult[A[T]] is an FResult[Top],
// or some conversion is possible
case b: B[_] => fOnB(b)
}
If is both legal and safe to call a generic method, such as fOnA[T] with an existential (a matching A[_])
However, it might be difficult to convince the compiler that the parameter you pass to f or the result you get are ok, given the reduced information of the existential. If so, please post the signatures you need.
Let's say I have a coproduct (a sealed trait) such as
sealed trait Traity
case object Foo extends Traity
case class Bar() extends Traity
case class Baz() extends Traity
Using shapeless, I can apply polymorphic functions to specific instances but what I'd like to do is to apply a zero-parameter (no-instance) polymorphic function to all the products (i.e. case classes and case objects). I have no idea what the syntax would look like, but something conceptually like:
object mypoly extends Poly1 {
implicit def traity[T <: Traity] = when[T]( getClass[T].toString )
}
iterate[Traity](mypoly) // gives List("Foo", "Bar", "Baz")
would suit my purposes.
For the example use case in your question, this is actually very straightforward:
import shapeless._
class NameHelper[A] {
def apply[C <: Coproduct, K <: HList]()(implicit
gen: LabelledGeneric.Aux[A, C],
keys: ops.union.Keys.Aux[C, K],
toSet: ops.hlist.ToTraversable.Aux[K, Set, Symbol]
): Set[String] = toSet(keys()).map(_.name)
}
def names[A] = new NameHelper[A]
And then:
scala> names[Traity]()
res0: Set[String] = Set(Bar, Baz, Foo)
(I'm using a Set since the order you're getting is just alphabetical—it's not currently possible to enumerate the constructors in declaration order, although I'd personally prefer that.)
If you'd like a more generic answer, an adaptation of the code in the question I linked above shouldn't be too bad—I'd be happy to add it here later.
I fail to understand why I am getting an “inferred type arguments do not conform to type parameter bounds”.
First, I defined a trait called CS which may be implemented by several classes (e.g., CS01 and CS02):
trait CS[+T <: CS[T]] {
this: T =>
def add: T
def remove: T
}
class CS01 extends CS[CS01] {
def add: CS01 = new CS01
def remove: CS01 = new CS01
}
class CS02 extends CS[CS02] {
def add: CS02 = new CS02
def remove: CS02 = new CS02
}
The idea is to keep the implemented type when calling add or remove on CS01 and CS02.
Secondly, I would like to define operations that may be executed on every classes compliant with trait CS. Then, I defined a trait called Exec(with two very simple examples of classes Exec01 and Exec02 mixin the Exec traits):
trait Exec {
def exec[U <: CS[U]](x: U): U
}
class Exec01 extends Exec {
def exec[U <: CS[U]](x: U): U = x.add
}
class Exec02 extends Exec {
def exec[U <: CS[U]](x: U): U = x.remove
}
Once again, I need to keep the implemented type of the class that mixes the CS trait. That is why exec is parametrized with [U <: CS[U]].
Finally, I want any CS enabling operations on it to mixin the trait Executable which makes it possible to execute an operation that follows trait Exec:
trait Executable[T <: CS[T]] {
this: T =>
def execute(e: Exec): T = e.exec(this)
}
However, I get the following error when I am trying to compile:
error: inferred type arguments [this.Executable[T] with T] do not conform to method exec's type parameter bounds [U <: this.CS[U]]
def execute(e: Exec): T = e.exec(this)
^
I don't quite understand because any classes that mix Executable must be of type T with the constraint of mixin the CS trait due to the bound in trait Executable[T <: CS[T]]. So, why this does not conform to the type parameter bound U <: CS[U] ?
Works if you specify the type parameter to exec explicitly:
def execute(e: Exec): T = e.exec[T](this)
Seems to be a limitation in the type inference.
Disclaimer: not a scala guru here, I'm learning it as I'm writing this.
First, let's simplify the example.
scala> trait Moo[+X <: Moo[X]]
defined trait Moo
scala> class Foo extends Moo[Foo]
defined class Foo
scala> def foobar[U <: Moo[U]](x: U) = x
foobar: [U <: Moo[U]](x: U)U
scala> foobar(new Foo)
res0: Foo = Foo#191275b
scala> class Bar extends Foo
defined class Bar
scala> foobar(new Bar)
<console>:12: error: inferred type arguments [Bar] do not conform to method
foobar's type parameter bounds [U <: Moo[U]]
foobar(new Bar)
^
scala>
foobar accepts a Foo argument but rejects a Bar which only extends Foo. Why? foobar is a generic, paramaterized by the type of its argument. It imposes a bound on that type. The type inferencer will not check each and every ancestor of the argument type, hoping to find one that satisfies the bound.
So how to impose a bound on an ancestor type? One method is with existential types.
scala> def foobar[V <: Moo[U] forSome {type U}](x: V) = x
foobar: [U <: Moo[_], V <: U](x: V)V
scala> foobar(new Foo)
res3: Foo = Foo#1154718
scala> foobar(new Bar)
res4: Bar = Bar#5a7ff7
scala>
Suppose I have an abstract class Bar that takes a type parameter:
abstract class Bar[A] { def get: A }
and I have a function that wants to instantiate some Bar objects, call their get methods and return the results:
def foo[A, B <: Bar[A]]: Seq[A]
It seems a little verbose to have to provide A as a separate type parameter, since it's implicit in B. What I would really like is to say
def foo[B <: Bar[A]]: Seq[A]
but that doesn't compile. Is there a way to make foo more compact?
What Daniel said in the comment.
Perhaps using an abstract type member will help reduce the verbosity.
abstract class Bar {
type A
def get: A
}
def foo[B <: Bar]: Seq[B#A]
def baz[B <: Bar](b: B): Seq[B#A]
def taz[B <: Bar](b: B): Seq[b.A]