Scala implicit unapply - scala

Am trying to implicitly deconstruct a class instance into a tuple to create a nicer DSL syntax.
Here's a simplified example of what I'm trying to do:
class Pair[A,B](a: A, b: B){
def left = a
def right = b
}
val pair = new Pair(1,2)
implicit def unpair[T1 <: Int, T2 <: Int](p: Pair[T1,T2]) = {
(p.left, p.right)
}
val(a,b) = pair
results in:
error: constructor cannot be instantiated to expected type;
found : (T1, T2)
required: Pair[Int,Int]
I know I can define a companion object with unapply method and manually handle the deconstruction (or call above implicit explicitly), but that makes for unwanted boilerplate.
Edit
Ok, just to provide a bit more context, Pair is embedded within an instance that implements map, flatMap, and withFilter (i.e. to be used within for comprehensions). So, desired usage looks something like:
val q = for{
(a,b) <- tableA join tableB on(...)
(c,d) <- tableC leftJoin tableD on(...)
....
} yield(a,b,c,d,...)
What I'd like to avoid is making Pair a case class (or adding a custom companion object to existing Pair class) and having to Pair(a,b) <- tableA join tableB on(...) everytime I join tables (read: often)
Original
Is there a way to pull this off in Scala 2.10 or 2.11?? There are some older SO threads from 2.8/2.9 days that indicate this functionality is not possible, but am hoping things have changed since then, or that there's a workaround available.

You need to set type of a and b explicit:
val(a,b): (Int, Int) = pair

If you just want to extract left and right (I'm guessing from your example), why not to solve your problem with even less code:
case class Pair[A, B](left: A, right: B)
val pair = Pair(1, 2)
val Pair(a, b) = pair
println(a, b)

Related

How to pass array of types in Scala?

I am trying to create a method that will take a list of Objects and a list of Types and then check whether a particular object matches a particular type.
I tried to create a dummy example. In the following code validate method takes list of objects and a List of type then tried to validate the types of each object. I know following code is wrong but I just created to communicate the problem, it would be really great if you can tell me how can I do this in Scala.
object T extends App {
trait MyT
case class A(a: Int) extends MyT
case class B(b: Int) extends MyT
def validate(values: Seq[Any], types: Seq[MyT]): Seq[Boolean] =
for ((v, ty: MyT) ← values.zip(types)) yield v.isInstanceOf[ty]
// create objects
val a = A(1)
val b = B(1)
// call validate method
validate(Seq(a, b), Seq(A, B))
}
Types are not values, so you can't have a list of them.
But, you may use Class instead:
def validate(values: Seq[Any], types: Seq[Class[_ <: MyT]]): Seq[Boolean] =
values.lazyZip(types).map {
case (v, c) =>
c.isInstance(v)
}
Which can be used like this:
validate(Seq(a, b), Seq(classOf[A], classOf[B]))
// res: Seq[Boolean] = List(true, true)
You can see the code running here.
However, note that this will break if your classes start to have type parameters due to type erasure.
Note, I personally don't recommend this code since, IMHO, the very definition of validate is a code smell and I would bet you have a design error that lead to this situation.
I recommend searching for a way to avoid this situation and solve the root problem.

Implementing Path dependent Map types in Shapeless

I am wanting to put together a map which contains path dependent type mapping from outer to inner:
import shapeless._
import shapeless.ops.hlist._
abstract class Outer {
type Inner
def inner: Inner
}
private case class Derp(hl: HList) {
def get(outer: Outer): outer.Inner = hl.select[outer.Inner]
def put(outer: Outer)(inner: outer.Inner): Derp = Derp(hl :: inner :: HNil)
def delete(outer: Outer)(c: outer.Inner): Derp = ???
}
The theory is that by using an HList, I can avoid using type selectors and ensure that programs can only get at an instance of Inner that was created by Outer.
Is this possible, or even a good idea? Most of the HList questions seem to be about arity and case classes, and I feel like I'm working outside the box.
Note that I am aware of https://stackoverflow.com/a/30754210/5266 but this question is about the Shapeless HList implementation in particular -- I don't know how to remove elements from HList and potentially return Option[outer.Inner].
First, you'll almost certainly need to parameterize Derp:
case class Derp[L <: HList](hl: L)
This is because whenever you have a Derp, the compiler will need to know what its static HList type is in order to do anything useful.
HList types encode the information about every type in the list – like
type Foo = Int :: String :: Boolean :: HNil
As soon as you say hl: HList, that information is lost.
Next, you'll want to properly specify the return types of your operations:
def get[O <: Outer](o: O)(implicit selector: Selector.Aux[L, o.type, o.Inner]): o.Inner = selector(hl)
def put[O <: Outer](o: O)(i: o.Inner): Derp[FieldType[o.type, o.Inner] :: L] = copy(hl = field[o.type](i))
This is "tagging" each Inner value with the Outer's type, so you can retrieve it later (which is what the Selector.Aux does). All interesting stuff in Shapeless happens through typeclasses that come with it (or that you define yourself), and they rely on type information to work. So the more type information you can retain in your operations, the easier it will be.
In this case, you'll never return Option, because if you try to access a value that isn't in the map, it won't compile. This is typically what you'd use HList for, and I'm not sure it matches your use case.
Shapeless also has HMap, which uses key-to-value mappings like a normal Map. The difference is that each key type can map to a different value type. This seems more in line with your use case, but it's organized a bit differently. To use HMap, you define a relation, as a type function. A type function is a typeclass with a dependent type:
trait MyRelation[Key] {
type Value
}
object MyRelation {
type Aux[K, V] = MyRelation[K] { type Value = V }
implicit val stringToInt: Aux[String, Int] = new MyRelation[String] { type Value = Int }
implicit val intToBool: Aux[Int, Boolean] = new MyRelation[Int] { type Value = Boolean }
}
Now you can define an HMap over MyRelation, so when you use String keys you'll add/retrieve Int values, and when you use Int keys you'll add/retrieve Boolean values:
val myMap = HMap[MyRelation.Aux]("Ten" -> 10, 50 -> true)
val myMap2 = myMap + ("Fifty" -> 50)
myMap2.get("Ten") // Some(10), statically known as Option[Int]
myMap2.get(44) // None, statically known as Option[Boolean]
This is a bit different from your example, in that you have a value with a dependent type, and you want to use the outer type as the key, and the inner type as the value. It's possible to express this as a relation for HMap as well, by using K#Inner =:= V as the relation. But it will often surprise you by not working, because path-dependent types are tricky and really depend on concrete subtypes of the outer (which will require a lot of boilerplate) or singleton types (which will be difficult to pass around without losing the necessary type information).

HList/KList from class values

I want to be able to create a class/trait that behaves somewhat like an enumeration (HEnum in the first snippet below). I can't use a plain enumeration because each enum value could have a different type (though the container class will be the same): Key[A]. I'd like to be able to construct the enum roughly like this:
class Key[A](val name: String)
object A extends HEnum {
val a = new Key[String]("a")
val b = new Key[Int]("b")
val c = new Key[Float]("c")
}
And then I'd like to be able to perform more or less basic HList operations like:
A.find[String] // returns the first element with type Key[String]
A.find("b") // returns the first element with name "b", type should (hopefully) be Key[Int]
So far I've been playing with an HList as the underlying data structure, but constructing one with the proper type has proven difficult. My most successful attempt looks like this:
class Key[A](val name: String)
object Key {
def apply[A, L <: HList](name: String, l: L): (Key[A], Key[A] :: L) = {
val key = new Key[A](name)
(key, key :: l)
}
}
object A {
val (a, akeys) = Key[String, HNil]("a", HNil)
val (b, bkeys) = Key[Int, Key[String] :: HList]("b", akeys)
val (c, ckeys) = Key[Float, Key[Int] :: HList]("c", bkeys)
val values = ckeys // use this for lookups, etc
def find[A]: Key[A] = values.select[A]
def find[A](name: String): Key[A] = ...
}
The problem here is that the interface is clunky. Adding a new value anywhere besides the end of the list of values is error prone and no matter what, you have to manually update values any time a new value is introduced. My solution without HList involved a List[Key[_]] and error prone/unsafe casting to the proper type when needed.
EDIT
I should also mention that the enum example found here is not particularly helpful to me (although, if that can be adapted, then great). The added compiler checks for exhaustive pattern matches are nice (and I would ultimately want that) but this enum still only allows a homogeneous collection of enum values.

How to deep copy classes with traits mixed in

Here's some sample scala code.
abstract class A(val x: Any) {
abstract def copy(): A
}
class b(i: Int) extends A(i) {
override def copy() = new B(x)
}
class C(s: String) extends A(s) {
override def copy() = new C(x)
}
//here's the tricky part
Trait t1 extends A {
var printCount = 0
def print = {
printCount = printCount + 1
println(x)
}
override def copy = ???
}
Trait t2 extends A {
var doubleCount = 0
def doubleIt = {
doubleCount = doubleCount + 1
x = x+x
}
override def copy = ???
}
val q1 = new C with T1 with T2
val q2 = new B with T2 with T1
OK, as you've likely guessed, here's the question.
How can I implement copy methods in T1 and T2, such that weather they are mixed in with B, C, or t2/t1, I get a copy of the whole ball of wax?
for example, q2.copy should return a new B with T2 with T1, and q1.copy should return a new C with T1 with T2
Thanks!
Compositionality of object construction
The basic problem here is, that, in Scala as well as in all other languages I know, object construction doesn't compose. Consider two abstract operations op1 and op2, where op1 makes property p1 true and where op2 makes property p2 true. These operations are composable with respect to a composition operation ○, if op1 ○ op2 makes both p1 and p2 true. (Simplified, properties also need a composition operation, for example conjunction such as and.)
Let's consider the new operation and the property that new A(): A, that is, an object created by calling new A is of type A. The new operation lacks compositionality, because there is no operation/statement/function f in Scala that allows you to compose new A and new B such that f(new A, new B): A with B. (Simplified, don't think too hard about whether A and B must be classes or traits or interfaces or whatever).
Composing with super-calls
Super-calls can often be used to compose operations. Consider the following example:
abstract class A { def op() {} }
class X extends A {
var x: Int = 0
override def op() { x += 1 }
}
trait T extends A {
var y: String = "y"
override def op() { super.op(); y += "y" }
}
val xt = new X with T
println(s"${xt.x}, ${xt.y}") // 0, y
xt.op()
println(s"${xt.x}, ${xt.y}") // 1, yy
Let X.op's property be "x is increased by one" and let T.op's property be "y's length is increased by one". The composition achieved with the super-call fulfils both properties. Hooooray!
Your problem
Let's assume that you are working with a class A which has a field x, a trait T1 which has a field y and another trait T2 which has a field z. What you want is the following:
val obj: A with T1 with T2
// update obj's fields
val objC: A with T1 with T2 = obj.copy()
assert(obj.x == objC.x && obj.y == objC.y && obj.z == objC.z)
Your problem can be divided into two compositionality-related sub-problems:
Create a new instance of the desired type. This should be achieved by a construct method.
Initialise the newly created object such that all its fields have the same values (for brevity, we'll only work with value-typed fields, not reference-typed ones) as the source object. This should be achieved by a initialise method.
The second problem can be solved via super-calls, the first cannot. We'll consider the easier problem (the second) first.
Object initialisation
Let's assume that the construct method works as desired and yields an object of the right type. Analogous to the composition of the op method in the initial example we could implement initialise such that each class/trait A, T1 and T2 implements initialise(objC) by setting the fields it knows about to the corresponding values from this (individual effects), and by calling super.initialise(objC) in order to compose these individual effects.
Object creation
As far as I can see, there is no way to compose object creation. If an instance of A with T1 with T2 is to be created, then the statement new A with T1 with T2 must be executed somewhere. If super-calls could help here, then something like
val a: A = new A // corresponds to the "deepest" super-call
val at1: A with T1 = a with new T1
would be necessary.
Possible solutions
I implemented a solution (see this gist) based on abstract type members and explicit mixin classes (class AWithT1WithT2 extends A with T1 with T2; val a = new AWithT1WithT2 instead of val a = new A with T1 with T2). It works and it is type-safe, but it is neither particularly nice nor concise. The explicit mixin classes are necessary, because the construct method of new A with T1 with T2 must be able to name the type it creates.
Other, less type-safe solutions are probably possible, for example, casting via asInstanceOf or reflection. I haven't tried something along those lines, though.
Scala macros might also be an option, but I haven't used them yet and thus don't know enough about them. A compiler plugin might be another heavy-weight option.
That is one of the reasons, why extending case classes is deprecated. You should get a compiler warning for that. How should the copy method, that is defined in A, know, that there may also be a T or whatever? By extending the case class,
you break all the assumptions, that the compiler made, when generating methods like equals, copy and toString.
The easiest and simplest answer is to make your concrete types into case classes. Then you get the compiler-supplied copy method which accepts named parameters for all the class's constructor parameters so you can selectively differentiate the new value from the original.

Impredicative types vs. plain old subtyping

A friend of mine posed a seemingly innocuous Scala language question last week that I didn't have a good answer to: whether there's an easy way to declare a collection of things belonging to some common typeclass. Of course there's no first-class notion of "typeclass" in Scala, so we have to think of this in terms of traits and context bounds (i.e. implicits).
Concretely, given some trait T[_] representing a typeclass, and types A, B and C, with corresponding implicits in scope T[A], T[B] and T[C], we want to declare something like a List[T[a] forAll { type a }], into which we can throw instances of A, B and C with impunity. This of course doesn't exist in Scala; a question last year discusses this in more depth.
The natural follow-up question is "how does Haskell do it?" Well, GHC in particular has a type system extension called impredicative polymorphism, described in the "Boxy Types" paper. In brief, given a typeclass T one can legally construct a list [forall a. T a => a]. Given a declaration of this form, the compiler does some dictionary-passing magic that lets us retain the typeclass instances corresponding to the types of each value in the list at runtime.
Thing is, "dictionary-passing magic" sounds a lot like "vtables." In an object-oriented language like Scala, subtyping is a much more simple, natural mechanism than the "Boxy Types" approach. If our A, B and C all extend trait T, then we can simply declare List[T] and be happy. Likewise, as Miles notes in a comment below, if they all extend traits T1, T2 and T3 then I can use List[T1 with T2 with T3] as an equivalent to the impredicative Haskell [forall a. (T1 a, T2 a, T3 a) => a].
However, the main, well-known disadvantage with subtyping compared to typeclasses is tight coupling: my A, B and C types have to have their T behavior baked in. Let's assume this is a major dealbreaker, and I can't use subtyping. So the middle ground in Scala is pimps^H^H^H^H^Himplicit conversions: given some A => T, B => T and C => T in implicit scope, I can again quite happily populate a List[T] with my A, B and C values...
... Until we want List[T1 with T2 with T3]. At that point, even if we have implicit conversions A => T1, A => T2 and A => T3, we can't put an A into the list. We could restructure our implicit conversions to literally provide A => T1 with T2 with T3, but I've never seen anybody do that before, and it seems like yet another form of tight coupling.
Okay, so my question finally is, I suppose, a combination of a couple questions that were previously asked here: "why avoid subtyping?" and "advantages of subtyping over typeclasses" ... is there some unifying theory that says impredicative polymorphism and subtype polymorphism are one and the same? Are implicit conversions somehow the secret love-child of the two? And can somebody articulate a good, clean pattern for expressing multiple bounds (as in the last example above) in Scala?
You're confusing impredicative types with existential types. Impredicative types allow you to put polymorphic values in a data structure, not arbitrary concrete ones. In other words [forall a. Num a => a] means that you have a list where each element works as any numeric type, so you can't put e.g. Int and Double in a list of type [forall a. Num a => a], but you can put something like 0 :: Num a => a in it. Impredicative types is not what you want here.
What you want is existential types, i.e. [exists a. Num a => a] (not real Haskell syntax), which says that each element is some unknown numeric type. To write this in Haskell, however, we need to introduce a wrapper data type:
data SomeNumber = forall a. Num a => SomeNumber a
Note the change from exists to forall. That's because we're describing the constructor. We can put any numeric type in, but then the type system "forgets" which type it was. Once we take it back out (by pattern matching), all we know is that it's some numeric type. What's happening under the hood, is that the SomeNumber type contains a hidden field which stores the type class dictionary (aka. vtable/implicit), which is why we need the wrapper type.
Now we can use the type [SomeNumber] for a list of arbitrary numbers, but we need to wrap each number on the way in, e.g. [SomeNumber (3.14 :: Double), SomeNumber (42 :: Int)]. The correct dictionary for each type is looked up and stored in the hidden field automatically at the point where we wrap each number.
The combination of existential types and type classes is in some ways similar to subtyping, since the main difference between type classes and interfaces is that with type classes the vtable travels separately from the objects, and existential types packages objects and vtables back together again.
However, unlike with traditional subtyping, you're not forced to pair them one to one, so we can write things like this which packages one vtable with two values of the same type.
data TwoNumbers = forall a. Num a => TwoNumbers a a
f :: TwoNumbers -> TwoNumbers
f (TwoNumbers x y) = TwoNumbers (x+y) (x*y)
list1 = map f [TwoNumbers (42 :: Int) 7, TwoNumbers (3.14 :: Double) 9]
-- ==> [TwoNumbers (49 :: Int) 294, TwoNumbers (12.14 :: Double) 28.26]
or even fancier things. Once we pattern match on the wrapper, we're back in the land of type classes. Although we don't know which type x and y are, we know that they're the same, and we have the correct dictionary available to perform numeric operations on them.
Everything above works similarly with multiple type classes. The compiler will simply generate hidden fields in the wrapper type for each vtable and bring them all into scope when we pattern match.
data SomeBoundedNumber = forall a. (Bounded a, Num a) => SBN a
g :: SomeBoundedNumber -> SomeBoundedNumber
g (SBN n) = SBN (maxBound - n)
list2 = map g [SBN (42 :: Int32), SBN (42 :: Int64)]
-- ==> [SBN (2147483605 :: Int32), SBN (9223372036854775765 :: Int64)]
As I'm very much a beginner when it comes to Scala, I'm not sure I can help with the final part of your question, but I hope this has at least cleared up some of the confusion and given you some ideas on how to proceed.
#hammar's answer is perfectly right. Here is the scala way of doint it. For the example i'll take Show as the type class and the values i and d to pack in a list :
// The type class
trait Show[A] {
def show(a : A) : String
}
// Syntactic sugar for Show
implicit final class ShowOps[A](val self : A)(implicit A : Show[A]) {
def show = A.show(self)
}
implicit val intShow = new Show[Int] {
def show(i : Int) = "Show of int " + i.toString
}
implicit val stringShow = new Show[String] {
def show(s : String) = "Show of String " + s
}
val i : Int = 5
val s : String = "abc"
What we want is to be able run the following code
val list = List(i, s)
for (e <- list) yield e.show
Building the list is easy but the list won't "remember" the exact type of each of its elements. Instead it will upcast each element to a common super type T. The more precise super super type between String and Int being Any, the type of the list is List[Any].
The problem is: what to forget and what to remember? We want to forget the exact type of the elements BUT we want to remember that they are all instances of Show. The following class does exactly that
abstract class Ex[TC[_]] {
type t
val value : t
implicit val instance : TC[t]
}
implicit def ex[TC[_], A](a : A)(implicit A : TC[A]) = new Ex[TC] {
type t = A
val value = a
val instance = A
}
This is an encoding of the existential :
val ex_i : Ex[Show] = ex[Show, Int](i)
val ex_s : Ex[Show] = ex[Show, String](s)
It pack a value with the corresponding type class instance.
Finally we can add an instance for Ex[Show]
implicit val exShow = new Show[Ex[Show]] {
def show(e : Ex[Show]) : String = {
import e._
e.value.show
}
}
The import e._ is required to bring the instance into scope. Thanks to the magic of implicits:
val list = List[Ex[Show]](i , s)
for (e <- list) yield e.show
which is very close to the expected code.