In few examples, I have seen that an object or a class extends Function1.
E.g. object Cash extends (CashProduct => String) in Hidden features of Scala
(I suppose A => B means Function1)
What it the benefit of extending a Function1?
The full example of what you provided:
object Cash extends (CashProduct => String) {
def apply(p: CashProduct) = p.currency.name + "="
def unapply(s: String)(implicit ps: ProductService): Option[CashProduct] = {
if (s.endsWith("=")
Some(ps.findCash(s.substring(0,3)))
else None
}
}
Shows that OP wanted to gain the syntactical benefit of the apply method, which allows your to create an instance calling Cash(...).
But why would you really want to extend a function? Lets look at a better case perhaps, List[T].
If we look up the long inheritance hierarchy, we'll see that:
trait Seq[+A] extends PartialFunction[Int, A]
Hmm, why does Seq extend PartialFunction[Int, A] (which in turns inherits Function1[A, B]? Because if we think about it, if I pass a List[A] an Int, representing the index of the element I'm seeking, it will (not efficiently) return me the element at that given index (if present).
The benefit of extending Function1 as compared to just defining apply is just that you can pass this object where a Function1 is expected. E.g.
val products: List[CashProduct] = ...
products.map(Cash)
Without the extends it would have to be written as
val products: List[CashProduct] = ...
products.map(Cash(_))
// or products.map(Cash.apply)
Related
I would like to define a List of elements implementing a common type class. E.g.
trait Show[A] {
def show(a: A): String
}
implicit val intCanShow: Show[Int] = new Show[Int] {
def show(int: Int): String = s"int $int"
}
implicit val stringCanShow: Show[String] = new Show[String] {
def show(str: String): String = str
}
The problem is, how to define a list = List(1, "abc") such that it is guaranteed that a Show instance for these values is in scope? I would then like to map this list over show like list map {_.show}.
I will first sketch a solution, and then explain why the naive approach with List[Any](1, "abc") cannot work.
What you can do
Define a wrapper class that can hold instances of type A together with instances of Show[A]:
case class Showable[A](a: A, showInst: Show[A]) {
def show: String = showInst.show(a)
}
Define your list as List[Showable[_]]:
var showableList: List[Showable[_]] = Nil
Maybe define a separate method to fill this list (consider packing the list itself and the builder-method in a class):
def addShowable[A: Show](a: A): Unit = {
showableList ::= Showable[A](a, implicitly[Show[A]])
}
Alternatively, you can carefully add a (very tightly scoped) implicit conversion:
implicit def asShowable[A](a: A)(implicit s: Show[A]): Showable[A] =
Showable(a, s)
and then costruct your list as follows (note the explicit type ascription):
val showableList = List[Showable[_]](1, "abc")
Now you can go through the list and call show:
showableList.map(_.show)
to obtain a list of String.
What you cannot do
You cannot simply define
val list: List[Any] = List(1, "abc", <showable3>, ..., <showableN>)
and then expect to be able to call show, because in order to call Show.show, you need actual Show instances. These things are not some type-hints that can be erased at runtime, they are actual objects, and they must be supplied by the compiler. Once you have created a List[Any], all is lost, because all the types are merged into an unexpressive upper bound Any, and the compiler has no way to inject all the necessary implicits Show[T_1],..., Show[T_N]. The argument is very similar to the third section "Dealing with implicits when defining interpreter for the Free monad" of this lengthy answer of mine.
An alternative way of handling this would be to use the shapeless library.
I would really reccommend this book which explains shapeless in a clear and concise manner.
Shapeless provides two things that I think will help you in this case:
Heterogeneous lists (HList)
Polymorphic functions to enable the HList mapping operation.
First import the required libraries (shapeless):
import shapeless.{HNil, Poly1, ::}
Create a heterogeneous list of whatever types you require. Note the type annotation is only there for clarity.
val data : Int :: String :: HNil = 1 :: "hello" :: HNil
Create a polymorphic function defining an implicit value for every type you require.
object Show extends Poly1 {
implicit def atT[T: Show] = at[T] (implicitly[Show[T]].show)
}
Shapeless provides an extension method for map on a HList to enable applying the show function to every element in the list
val result : String :: String :: HNil = data.map(Show)
Edited: thanks to #dk14 for the suggested improvement to the definition of the Show polymorphic function.
The core problem here is that you want to create a heterogenous list, something like List[Int, String] instead of List[Any]. This means you need a different structure that would preserve Int and String types, but still would be "mappable" like List. The one structure in scala-library that can contain heterogenous types is Tuple:
val tuple = (1, "abc")
val result = List(implicitly[Show[Int]].show(tuple._1), implicitly[Show[Int]].show(tuple._2))
However, scala-library can't map over tuples - you might want some syntax sugar for better readability.
So the obvious solution is HList from Shapeless: Int :: String :: HNil (or you can use tuple ops and stay with (Int, String))
import shapeless._
import poly._
//show is a polymorphic function
//think of it as `T => String` or even `(Show[T], T) => String`
object show extends Poly1 {
implicit def atT[T: Show] = at[T](implicitly[Show[T]].show)
}
# (1 :: "aaaa" :: HNil) map show
res8: String :: String :: HNil = "int 1" :: "aaaa" :: HNil
Or you could use at[Int]/at[String] instead of type-classes, like in #Steve Robinson's answer.
P.S. The lib could be found here. They also provide one-liner to get Ammonite REPL with shapeless integrated, so you could try my example out using:
curl -s https://raw.githubusercontent.com/milessabin/shapeless/master/scripts/try-shapeless.sh | bash
Notes:
Practically Shapeless solution requires as same amount of maintenance as Tuple-based one. This is because you have to keep track of your Int and String types anyways - you can never forget about those (unlike in homogenous List[T] case). All Shapeless does for you is nicer syntax and sometimes better type inference.
If you go with tuples - you can improve readability by using implicit class instead of Haskell-like style, or if you still want Haskell-like, there is a Simulacrum macro for better type-class syntax.
Given that other scala-library-only alternatives just capture type class instances inside some regular class, you could be better off with a regular OOP wrapper class:
trait Showable[T]{def value: T; def show: String}
class IntShow(val value: Int) extends Showable[Int]{..}
class StringShow(val value: String) extends Showable[String] {..}
val showables: List[Showable[_]] = List(new Showable(5), new Showable("aaa"))
showables.map(_.show)
Looks cleaner and more readable to me :)
If you like to rewrite dynamic dispatching in FP-style:
sealed trait Showable
final case class ShowableInt(i: Int) extends Showable
final case class ShowableString(s: String) extends Showable
implicit class ShowableDispatch(s: Showable){
def show = s match{ //use `-Xfatal-warnings` scalac option or http://www.wartremover.org/ to guarantee totality of this function
case ShowableInt(i) => ...
case ShowableString(s) => ...
}
}
List(ShowableInt(5), ShowableString("aaa")).map(_.show)
If you really want static dispatching (or ad-hoc polymorphism), given that other solutions introduce Showable[_] which is practically Showable[Any]:
case class Showable[T](v: T, show: String)
def showable(i: Int) = Showable(i, s"int $i")
def showable(s: String) = Showable(i, s)
List(showable(5), showable("aaa")).map(_.show)
Disclamer: I've made this answer to provide a solution to the concrete development problem, and not the theoretical problem of using typeclass
I would do it this way:
trait Showable{ def show(): String }
implicit class IntCanShow(int: Int) extends Showable {
def show(): String = s"int $int"
}
implicit class StringCanShow(str: String) extends Showable {
def show(): String = str
}
val l: List[Showable] = List(1,"asd")
Note that I changed the meaning of the trait Show, into Showable, such that the implementing classes are used as wrapper. We can thus simply require that we want Showable instances
(and because those classes are implicit, input of the List are automatically wrapped)
I'm reading through and working my way through using type classes and I came across this way of defining type classes from the Shapeless guide:
So here goes the example:
object CsvEncoder {
// "Summoner" method
def apply[A](implicit enc: CsvEncoder[A]): CsvEncoder[A] =
enc
// "Constructor" method
def instance[A](func: A => List[String]): CsvEncoder[A] =
new CsvEncoder[A] {
def encode(value: A): List[String] =
func(value)
}
// Globally visible type class instances
}
What I do not understand is the need for the apply method? What is it doing in this context above?
Later on, the guide describes how I could create a type class instance:
implicit val booleanEncoder: CsvEncoder[Boolean] =
new CsvEncoder[Boolean] {
def encode(b: Boolean): List[String] =
if(b) List("yes") else List("no")
}
is actually shortened to:
implicit val booleanEncoder: CsvEncoder[Boolean] =
instance(b => if(b) List("yes") else List("no"))
So my question now is, how does this work? What I do not get is the need for the apply method?
EDIT: I came across a blog post that describes the steps in creating type classes as below:
Define typeclass contract trait Foo.
Define a companion object Foo with a helper method apply that acts like implicitly, and a way of defining Foo instances typically from a function.
Define FooOps class that defines unary or binary operators.
Define FooSyntax trait that implicitly provides FooOps from a Foo instance.
So what is the deal with point number 2, 3 and 4?
Most of those practices came from Haskell (basically an intention to mimic Haskell's type-classes is a reason for so much boilerplate), some of it is just for convenience. So,
2) As #Alexey Romanov mentioned, companion object with apply is just for convenience, so instead of implicitly[CsvEncoder[IceCream]] you could write just CsvEncoder[IceCream] (aka CsvEncoder.apply[IceCream]()), which will return you a required type-class instance.
3) FooOps provides convenience methods for DSLs. For instance you could have something like:
trait Semigroup[A] {
...
def append(a: A, b: A)
}
import implicits._ //you should import actual instances for `Semigroup[Int]` etc.
implicitly[Semigroup[Int]].append(2,2)
But sometimes it's inconvenient to call append(2,2) method, so it's a good practice to provide a symbolic alias:
trait Ops[A] {
def typeClassInstance: Semigroup[A]
def self: A
def |+|(y: A): A = typeClassInstance.append(self, y)
}
trait ToSemigroupOps {
implicit def toSemigroupOps[A](target: A)(implicit tc: Semigroup[A]): Ops[A] = new Ops[A] {
val self = target
val typeClassInstance = tc
}
}
object SemiSyntax extends ToSemigroupOps
4) You can use it as follows:
import SemiSyntax._
import implicits._ //you should also import actual instances for `Semigroup[Int]` etc.
2 |+| 2
If you wonder why so much boilerplate, and why scala's implicit class syntax doesn't provide this functionality from scratch - the answer is that implicit class actually provides a way to create DSL's - it's just less powerful - it's (subjectively) harder to provide operation aliases, deal with more complex dispatching (when required) etc.
However, there is a macro solution that generates boilerplate automatically for you: https://github.com/mpilquist/simulacrum.
One another important point about your CsvEncoder example is that instance is convenience method for creating type-class instances, but apply is a shortcut for "summoning" (requiring) those instances. So, first one is for library extender (a way to implement interface), another one is for a user (a way to call a particular operation provided for that interface).
Another thing to note is that in shapeless the apply method is not only for cuter syntax.
Take for instance this simplified version of shapeless' Generic and some case class Foo.
trait Generic[T] {
type Repr
}
object Generic {
def apply[T](implicit gen: Generic[T]): Generic[T] { type Repr = gen.Repr } = gen
/* lots of macros to generate implicit instances omitted */
}
case class Foo(a: Int, b: String)
Now when I call Generic[Foo] I will get an instance that is typed as Generic[Foo] { type Repr = Int :: String :: HNil }. But if I call implicitly[Generic[Foo]] all the compiler knows about the result is that it's a Generic[Foo]. In other words: the concrete type of Repr is lost and I can't do anything useful with it. The reason is that implicitly is implemented as follows:
def implicitly[T](implicit e: T): T = e
That method declaration basically says: if you ask for a T I promise to give you a T, if I find one, and nothing more. So that means you'd have to ask implicitly[Generic[Foo] { type Repr = Int :: String :: HNil }] and that defeats the purpose of having automatic derivation.
Quoting the guide immediately after the object CsvEncoder definition:
The apply method ... allows us to summon a type class instance given a target type:
CsvEncoder[IceCream]
// res9: CsvEncoder[IceCream] = ...
I'm trying to add new functions to existing types (so I can have the IDE auto suggest relevant functions for types I don't have control over, eg Future[Option[A]]). I've explored both implicit classes and implicit conversions to accomplish this and they both seem to offer the same behavior.
Is there any effective difference between using an implicit class:
case class Foo(a: Int)
implicit class EnrichedFoo(foo: Foo) {
def beep = "boop"
}
Foo(1).beep // "boop"
And using an implicit conversion:
case class Foo(a: Int)
trait Enriched {
def beep: String
}
implicit def fooToEnriched(foo: Foo) = new Enriched {
def beep = "boop"
}
Foo(1).beep // "boop"
I suppose one difference here might be that the first example creates a one-off class instead of a trait, but I could easily adapt the implicit class to extend an abstract trait, eg:
case class Foo(a: Int)
trait Enriched {
def beep: String
}
implicit class EnrichedFoo(foo: Foo) extends Enriched {
def beep = "boop"
}
Foo(1).beep // "boop"
As far as I'd know, they're pretty much exactly the same. The scoping rules also equally apply to both.
In my opinion, I'd use the implicit classes for your kind of situation. They were probably created exactly for something like that.
Implicit conversions, to me, are more appropriate when you already actually have two different kind of classes and want to convert between the two.
You can check out the initial proposal for implicit classes right here.
There it says:
A new language construct is proposed to simplify the creation of classes which provide extension methods to another type.
You can even see how it desugars implicit classes. The following:
implicit class RichInt(n: Int) extends Ordered[Int] {
def min(m: Int): Int = if (n <= m) n else m
...
}
will desugar into:
class RichInt(n: Int) extends Ordered[Int] {
def min(m: Int): Int = if (n <= m) n else m
...
}
implicit final def RichInt(n: Int): RichInt = new RichInt(n)
Well to me its a matter of preference. Actually the implicit classes came into being to ease the creation of classes which provide extension methods to another type.
Implicit classes add a lot of value to value classes though.
To add on Luka Jacobowitz answer: Implicit classes are basically extensions. Implicit conversion is used to tell the compiler that it may be treated as something with extension.
Sounds nearly the same. Two things of interest from implicit conversion to have some difference:
First: You may need to activate the language feature for disabling warnings when using implicit conversion.
Second: The term of "converting" the type may be confusing:
Implicit conversions are applied in two situations:
If an expression e is of type S, and S does not conform to the expression’s expected type T.
[Or:] In a selection e.m with e of type S, if the selector m does not denote a member of S.
case class Foo(a: Int)
trait Enriched {
def beep: String
}
implicit def fooToEnriched(foo: Foo) = new Enriched {
def beep = "boop"
}
Foo(1) match {
case _:Enriched => println("is an Enriched")
case _:Foo => println("no, was a Foo")
}
// no, was a Foo
but it may be treated as an Enriched...
val enriched: Enriched = Foo(2)
enriched match {
case _:Enriched => println("is an Enriched")
case _:Foo => println("no, was a Foo")
}
// is an Enriched
// plus unreachable code warning: case _:Foo => println("no, was a Foo")
I have some collection of type Collection[SuperType]. Stored in this collection are several values that are subtypes of SuperType, I would like the collection to only allow itself to contain one instance of each subtype (A bit like a set, but not).
I am trying to write a function that when given the companion object of one of the above mentioned subtypes, can return the first instance of the class the companion object belongs to.
Initially I tried with a Set as shown below, but T will suffer from type erasure, so the pattern matching will fail. I then also realised a Set wasn't suitable for this task, because I only want one occurrence of each subtype in the collection.
def get[T <: SuperType](target: T): Option[SuperType] =
collection.collectFirst({
case target: T => target
})
My next, and current approach is using a map, where the key is a companion object and the value is an instance of the companion object's class. The type hierarchy is show below.
trait SuperType
trait SuperTypeValue
// Pretend this has some parameters
case class ExampleSubType extends SuperTypeValue
case object ExampleSubType extends SuperType {
// value for use in later example
val uniqueToObjectField: String = "hello"
}
val collection: Map[SuperType, SuperTypeValue] = // Some new map
def get(target: SuperType): Option[SuperTypeValue] =
collection.get(target)
The above works well enough. However, I would like to preserve the type of the subtype that is used as the parameter, and use it as the return type. I believe the signature of the function would look something like this:
get[T <: SuperType](target: T): Option[T]
// So I could then do something like this
get(ExampleSubType) match {
case Some(exampleSubType) => exampleSubType.uniqueToObjectField
case _ => "nope"
}
Is this possible within scala? If so, how? If not, does this exist in other languages and what is it called?
Hopefully there are no glaring issues with this question, but it's 2am so I shall check things over again in the morning.
You can use ClassTags to get around the type erasure. Instead of using the companion object, it might be easier to just provide the generic parameter explicitly:
import scala.reflect._
trait SuperType { val x: Int }
case class Foo(x: Int) extends SuperType
case class Bar(x: Int) extends SuperType
val collection = Set(Foo(1), Foo(2), Bar(3), Foo(4), Bar(5))
def get[T <: SuperType : ClassTag]: Option[T] = {
collection.collectFirst {
case target: T => target
}
}
And then you can call:
get[Foo] //Foo(1)
get[Bar] //Bar(3)
You are trying to use a hammer when you need a saw. You should just make a new class for this with a field for each type.
class SomeClass{
a:TypeA
b:TypeB
c:TypeC
// if c extends b extends a maybe you want
// to prevent a TypeC being assigned to A I have no idea
// you can change these implementations to get the behavior you want
addA(a:TypeA){ this.a = a}
addB(b:TypeB){ this.b = b}
addC(c:TypeC){ this.c = c}
}
Often novices try use collections for crazy purposes. Just because a collection holds data, doesn't mean any time you want to hold data you need one. You need to think about what your requirements are first before you decide what you are going to use, not the other way around, you will be on SO for the rest of your programming life if you take that approach.
I have two case classes
case class StringCaseClass(argument: String)
case class IntCaseClass(argument: Int)
I want to define a structural type which will match the companion object of both of these
type HasApply1 {
def apply[A, R](argument: A): R
}
This will compile fine, but when I try to use it like this
def method(caseClass: HasApply1) {
// whatever
}
method(StringCaseClass)
I will get a compiler error
found : StringCaseClass.type
required: WithApply1
(which expands to) AnyRef{def apply[A, R](string: A): R}
Is there any way of accomplishing this? If I redefine the structural type to have concrete types for A and R it will compile correctly, but then I lose the flexiblity
#aloiscochard's comment is almost there. What he forgot to mention is that case class companion objects already implement the appropriate FunctionN trait, so you can simply do this,
scala> case class StringCaseClass(argument: String)
defined class StringCaseClass
scala> case class IntCaseClass(argument: Int)
defined class IntCaseClass
scala> def method[A, R](caseClass: A => R, a: A) = caseClass(a)
method: [A, R](caseClass: A => R, a: A)R
scala> method(StringCaseClass, "foo")
res0: StringCaseClass = StringCaseClass(foo)
scala> method(IntCaseClass, 23)
res1: IntCaseClass = IntCaseClass(23)
In general you should avoid structural typing as it's very expensive. The call will be converted into a reflection call because of limitations in the JVM. When you start using scala 2.10 structural types will result in a warning at compile time (though you could disable that using a flag).
If you're looking into a more general way to add functionality to classes that don't share an inheritance hierarchy you could use Type Classes.
Here's a quick example:
trait CanCreateRFromA[A,R]{
def createNew(a:A): R
}
implicit object CanCreateBlahFromInt extends CanCreateRFromA[Int,Blah2]{
def createNew(i:Int):Blah2 = new Blah2(i)
}
implicit object CanCreateBlah1FromString extends CanCreateRFromA[String,Blah1]{
def createNew(s:String):Blah1 = new Blah1(s)
}
case class Blah1(something:String)
case class Blah2(something:Int)
def createRFromA[A,R](a:A)(implicit tc:CanCreateRFromA[A,R])= tc.createNew(a)
Then you can call:
createRFromA(1) // This gives a Blah2
createRFromA("1") // This gives a Blah1
Again I'm not sure what you're trying to accomplish, but it probably is possible to do what you want with a type class and it will be much faster.
You didn't pass an instance of StringCaseClass to your method. What you passed there is companion object of StringCaseClass (which is automatically generated for case classes).
Try if this works: method(StringCaseClass("dummy")).