Reputation: 89
I just found the type class concept of Scala and like it actually very much. The problem I have it that all examples I found put the type classes (objects) under one object (Like here: http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html)
Maybe this is wrong but I am a friend of having one file per class. So what I like to do is to put the type classes into several files which would mean that each implementation needs to be put into a seperate object. This now leads to the "problem" that I need to import every single implementation manually. To clarify better here a small example:
package sth
import sth.like.Like
import sth.like.StringLike._
import sth.like.IntLike._
object Application extends App {
def t[T](arg: T)(implicit l: Like[T]) = {
l.print(arg)
}
t(1)
t("Blub")
}
-
package sth.like
trait Like[T] {
def print(arg: T)
}
-
package sth.like
object IntLike {
implicit object LikeIntLike extends Like[Int] {
def print(arg: Int): Unit = println(s"INT $arg")
}
}
-
package sth.like
object StringLike {
implicit object LikeStringLike extends Like[String] {
override def print(arg: String): Unit = println(s"STRING: $arg")
}
}
This works so far. I know, the wildcard import in Application is not necessary but that is not the point. As you can see I need to import both StringLike and IntLike in Application because otherwise these are not available for the Application object.
So is it possible to do this in a generic way or is it completely bad practise to do it this way?
Upvotes: 3
Views: 866
Reputation: 89
thank you very much for your answer. But I also would need to add new type classes manually to the Implicits, wouldn't I?
Couldn't I use then package objects for simplicity reasons like here:
http://naildrivin5.com/scalatour/wiki_pages/PackageObjects/
?
I mean this part:
package opower {
package object controller {
type Secured = org.springframework.security.access.annotation.Secured
type Controller = org.springframework.stereotype.Controller
...
}
}
Since it seems that there is no dynamic way I could just put all type classes into the controller object and could this then import.
Or do I missunderstand the package object?
Upvotes: 0
Reputation: 8663
You could put your implicits inside traits, not objects
trait IntLike {
implicit object LikeIntLike extends Like[Int] {
def print(arg: Int): Unit = println(s"INT $arg")
}
}
And then have object with the same name, extending this trait, which would give you what you had earlier, you can import each implicit individually.
object IntLike extends IntLike
You can do the same for all other instances of your typeclass:
trait StringLike {
implicit object LikeStringLike extends Like[String] {
override def print(arg: String): Unit = println(s"STRING: $arg")
}
}
object StringLike extends StringLike
And in another file, you can combine all traits together like this:
object Implicits extends StringLike with IntLike
and import just the Implicits
object if you want all your implicits in scope.
package sth
import sth.like.Like
import sth.like.Implicits._
object Application extends App {
def t[T](arg: T)(implicit l: Like[T]) = {
l.print(arg)
}
t(1)
t("Blub")
}
Optionally, you can mixin traits you need
object Application extends App with StringLike with IntLike { ... }
or even do
trait Implicits extends StringLike with IntLike
object Implicits extends Implicits
object Application extends App with Implicits { ... }
Upvotes: 6