I'm quite new to Scala but I already love it. I have read tutorials and articles on partial functions. What I would like to achieve is to have an object extending PartialFunction[...,...] and have it defined directly with cases, without needing to define isDefinedAt and apply methods.
For example
val partialfuncval : PartialFunction[Int,Boolean] = {
case 1 => false
}
is a valid definition of a partial function. But why can't I write
object PartialFunctionClass extends PartialFunction[Int,Boolean] {
case 1 => false
}
? This would cancel the need of defining isDefinedAt and apply and would make writing classes of certain (predefined by a lib I'm using) types easier.
Would one of these options suffice you?
Option 1
abstract class DelegatingPartialFunction[-T,+R](underlying: PartialFunction[T,R]) extends PartialFunction[T,R] {
def apply(t: T) = underlying.apply(t)
def isDefinedAt(t: T) = underlying.isDefinedAt(t)
}
Then:
object PartialFunctionClass extends DelegatingPartialFunction[Int,Boolean]({
case 1 => false
})
Option 2
trait DelegatingPartialFunction[-T,+R] extends PartialFunction[T,R] {
val underlying: PartialFunction[T,R]
def apply(t: T) = underlying.apply(t)
def isDefinedAt(t: T) = underlying.isDefinedAt(t)
}
Then:
object PartialFunctionClass extends DelegatingPartialFunction[Int,Boolean] {
val underlying = {
case 1 => true
}
}
Another option that might work depending on the use-case is
type PartialFunctionAlias = PartialFunction[Int,Boolean]
Then:
val partialfuncval: PartialFunctionAlias = {
case 1 => false
}
Related
I'm trying to go functional, but when working on real world problems I'm struggling, I need helps with a few basics. I like the idea of a type class and to add more implicit types in future.
trait Query {
def queryDetails: QueryDetails
}
case class LocalQueryType(queryDetails: QueryDetails) extends Query
case class JdbcQueryType(queryDetails: QueryDetails) extends Query
def queryTypeFactory(queryDetails: QueryDetails): Query = {
queryDetails.platform match {
case c if queryDetails.platform.contains("-file://") => LocalQueryType(queryDetails)
case _ => JdbcQueryType(queryDetails)
}
}
Then I have a type class that looks for the local or Jdbc types, but it doesn't work as it is receiving only Query type.
I've tried using generics like:
def queryTypeFactory[T<:Query](queryDetails: QueryDetails): T = {
queryDetails.platform match {
case c if queryDetails.platform.contains("-file://") => LocalQueryType(queryDetails)
case _ => JdbcQueryType(queryDetails)
}
}
Adding Type Class:
trait QueryTask[A] {
def runQuery(a: A): String
}
object QueryTask {
def apply[A](implicit sh: QueryTask[A]): QueryTask[A] = sh
object ops {
def runQuery[A: QueryTask](a: A) = QueryTask[A].runQuery(a)
implicit class ShowOps[A: QueryTask](a: A) {
def runQuery = QueryTask[A].runQuery(a)
}
}
implicit val localQuery: QueryTask[LocalQueryType] =
instance(localQueryType => s"running local: ${localQueryType.queryDetails.command} on platform: ${localQueryType.queryDetails.platform}")
implicit val jdbcQuery: QueryTask[JdbcQueryType] =
instance(jdbcQueryType => s"running jdbc: ${jdbcQueryType.queryDetails.command} on platform: ${jdbcQueryType.queryDetails.platform}")
def instance[A](func: A => String): QueryTask[A] =
new QueryTask[A] {
def runQuery(a: A): String = func(a)
}
The idea is to not use the usual OO factory or strategy pattern.
Type class approach seems not to work in your use case.
Implicits are resolved at compile time. So in order to decide which instance you need QueryTask[LocalQueryType] or QueryTask[JdbcQueryType] compiler has to know whether type A is LocalQueryType or JdbcQueryType at compile time.
But it seems you decide that depending on whether queryDetails.platform.contains("-file://") or not i.e. at runtime.
It seems you need usual pattern mathing. You should use type class pattern when it's necessary.
I have few classes which do not derive from any superclass. They all have bunch of same methods defined. For example,
class A {
def getMsgNum = 1
}
class B {
def getMsgNum = 2
}
I would like to write a generic function that will return message num based on object function is called with. So something like,
def getMsgNum[T](t: T) = t.getMsgNum
I think that because of type erasure I cannot expect that to work but I was looking at view bound and context bound with ClassTag but that still does not work.
def getType[T: ClassTag](msg: T) = {
msg.getMsgNum
}
I come from C++ background and I am trying to achieve something to the effect of template compilation for every type.
Thanks for your time!
I personally prefer adhoc polymorphism with TypeClass (http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html) pattern. I think it will be much more "true scala way" solution for this kind of problem. Also structural typing more expensive at runtime because it use reflection for field access.
class A
class B
trait ToMsgNum[T] {
def getMsgNum: Int
}
implicit object AToMsgNum extends ToMsgNum[A] {
def getMsgNum = 1
}
implicit object BToMsgNum extends ToMsgNum[B] {
def getMsgNum = 2
}
def getMsgNum[T: ToMsgNum](t: T) =
implicitly[ToMsgNum[T]].getMsgNum
println(getMsgNum(new A))
println(getMsgNum(new B))
def getMsgNum[T](t: T)(implicit ev: T => { def getMsgNum: Int }) = t.getMsgNum
where { def getMsgNum: Int } is a structural type. From the documentation:
A structural type is a type of the form Parents { Decls } where Decls contains declarations of new members that do not override any member in Parents.
and
Structural types provide great flexibility because they avoid the need to define inheritance hierarchies a priori
Please note that the above solution uses an implicit reflective call to access the field of the structural type, a language feature that has to be explicitly enabled by adding the import
import scala.language.reflectiveCalls
This is not too different from Eugene's solution but I think it's a bit clearer:
// predefined classes you have no access to
class Foo { def someMethod = "foo" }
class Bar { def someMethod = "bar" }
there's no way in Scala other than reflection or structural types (which is reflection in disguise) to generically call someMethod on these types. The way this can be made to work though, is by defining adapter objects that know how to deal with each type individually, and you then make generic calls on those instead:
trait HasSomeMethod[T] { def someMethod(x: T): String }
object FooHasSomeMethod extends HasSomeMethod[Foo] { def someMethod(x: Foo) = x.someMethod }
object BarHasSomeMethod extends HasSomeMethod[Bar] { def someMethod(x: Bar) = x.someMethod }
now you can pass one of those adapter objects into the method that needs generic access to Foo#someMethod and Bar#someMethod:
def invokeSomeMethod[T](x: T)(adapter: HasSomeMethod[T]) =
adapter.someMethod(x)
invokeSomeMethod(new Foo)(FooHasSomeMethod) // returns "foo"
invokeSomeMethod(new Bar)(BarHasSomeMethod) // returns "bar"
(we could have used a single parameter list here but later we'll nede 2 lists anyway)
however, this is obviously not as useful as we'd like as we have to pass in the adapter manually. Let's introduce implicits to make Scala automatically look up the right adapter object and pass that in to our generic but inheritance'less method:
implicit object FooHasSomeMethod extends HasSomeMethod[Foo] { ... }
implicit object BarHasSomeMethod extends HasSomeMethod[Bar] { ... }
def invokeSomeMethod[T](x: T)(implicit adapter: HasSomeMethod[T]) =
adapter.someMethod(x)
now these work:
invokeSomeMethod(new Foo) // returns "foo"
invokeSomeMethod(new Bar) // returns "bar"
The above 2 calls get translated automatically to the longer calls in the previous version; Scala looks up suitable values for the implicit adapter parameter automatically from the implicit objects (and also vals and defs, to be precise) available in the "environment" of the call.
You can also define invokeSomeMethod like this, which is just syntactic sugar over the above definition:
def invokeSomeMethod[T: HasSomeMethod](x: T) =
implicitly[HasSomeMethod[T]].someMethod(x)
or, since T: HasSomeMethod auto-generates a second parameter list implicit evidence$1: HasSomeMethod[T], this also works:
def invokeSomeMethod[T: HasSomeMethod](x: T) =
evidence$1.someMethod(x)
The above "pattern" is known as Type Classes. So for example the T: HasSomeMethod bit can be read as "some type T that belongs to the type class HasSomeMethod" (or "...has been made an instance of the type class HasSomeMethod").
For more on Type Classes, see e.g. http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html.
You can also define the HasSomeMethod type class instance for classes that don't even have someMethod nor bear no other resemblance to Foo and Bar whatsoever, if needed:
implicit object IntHasSomeMethod extends HasSomeMethod[Int] {
def someMethod(x: Int) = "this is an int: " + x
}
invokeSomeMethod(3) // returns "this is an int: 3"
If you need to define an instance of that type class for many classes, you can have a helper (with a name that matches the type class, for niceness):
def HasSomeMethod[T](fn: T => String) = new HasSomeMethod[T] {
def someMethod(x: T) = fn(x)
}
now you can define type class instances (adapters) very concisely:
implicit val FooHasSomeMethod = HasSomeMethod[Foo](_.someMethod)
implicit val BarHasSomeMethod = HasSomeMethod[Bar](_.someMethod)
implicit val IntHasSomeMethod = HasSomeMethod[Int]("this is an int: " + _)
implicit val PersonHasSomeMethod = HasSomeMethod[Person](_.name)
// etc
If you dont want to use structural type (reflection) and implicit, how about create Adaptor on top of it, so you own method getMsgNum will implement based on the Adaptor instead of already existing class.
class A {
def getMsgNum = 1
}
class B {
def getMsgNum = 2
}
class C {
def getMsgNum = 3
}
trait Adaptor[T] {
def getMsgNum: Int
}
class AdaptorA(t: A) extends Adaptor[A] {
def getMsgNum = t.getMsgNum
}
class AdaptorB(t: B) extends Adaptor[B] {
def getMsgNum = t.getMsgNum
}
class AdaptorC(t: C) extends Adaptor[C] {
def getMsgNum = t.getMsgNum
}
def getMsgNum[T](t: Adaptor[T]) = t.getMsgNum
getMsgNum(new AdaptorA(new A)) //1
getMsgNum(new AdaptorB(new B)) //2
getMsgNum(new AdaptorC(new C)) //3
I'm using the Akka actors library here. The actors library defines a partial function "receive" which an actor that extends "actor" must implement to deal with various messages. I am creating a trait hierarchy for my application where trait "clockActor" extends Actor and "MasterClock" and "SubClock" extend "clockActor". I'm looking to add the common functionality of clocks in to the "clock" trait's receive function but then how to I add extra functionality to the receive function in the master and sub clock traits?
In short, I need a way to add extra case statements to a partial function.
Ideas?
As already suggested, you could easily compose PartialFunctions using orElse
trait ClockActor {
def commonOp = {
case ... => ...
}
}
class MasterClock extends Actor with ClockActor {
def receive = commonOp orElse masterOp
def masterOp = {
case ... => ...
}
}
class SubClock extends Actor with ClockActor {
def receive = commonOp orElse subOp
def subOp = {
case ... => ...
}
}
One thing that comes to mind is to do something like this:
trait ClockActor {
def pf:PartialFunction[String, Boolean] = {
case "a" => true
case v if(_pf.isDefinedAt(v)) => _pf.apply(v)
}
def _pf:PartialFunction[String, Boolean] = Map.empty
}
object MasterClock extends ClockActor {
override def _pf:PartialFunction[String, Boolean] = {
case "b" => false
}
println(pf("a"))
println(pf("b"))
}
which will output:
scala> MasterClock
true
false
The value true comes from the definition in the partial function of the Trait ClockActor, the falsecomes from the Object MasterClock.
I am currently working on a E-Commerce application in scala / lift and cannot figure out how to match correctly on my type hierarchy. my current implementation is:
abstract trait BaseProduct[T <: BaseProduct[T]] extends MongoRecord[T] with ObjectIdPk[T] {
self:T =>
def whatever
...
}
abstract trait SimpleType[T <: BaseProduct[T]] extends BaseProduct[T] {
self:T =>
val producttype = "product/simple"
}
abstract trait ConfigurableType[T <: BaseProduct[T],E <: SimpleType[E]] extends BaseProduct[T] {
self: T =>
val producttype = "product/configurable"
}
class ClothingProduct extends SimpleType[ClothingProduct] {
def meta = ClothingProduct
}
class ConfigurableClothing extends ConfigurableType[ConfigurableClothing,ClothingProduct] {
val childmeta = ClothingProduct
val configurableFields = List(color,size)
def meta = ConfigurableClothing
}
With this in place I want to implement a Shopping Cart which should only take Products of Type SimpleType (and BaseProduct). It should also implement a function that takes any kind of BaseProduct with a pattern matching clause that should react to wheater it is a Simple or a Configurable Type.
My first implementations which drives me crazy due to Type Errors was:
object Cart extends SessionVar[List[CartItem]](List()) {
def addProduct(product:SimpleType[_],quantity:Int = 1) = {
this.get.partition(_.product.id.is == product.id.is) match {
case (Nil,xs) => this.set(CartItem(product,quantity) :: xs)
case (x,xs) => this.set(CartItem(product,x.head.quantity + quantity) :: xs)
}
}
}
case class CartItem(product:SimpleType[_], quantity:Int) {
def lineTotal:Double = quantity * product.price.is
}
With to following function to add a Cart Item:
def addBasketLink(prod:BaseProduct[_]) = {
prod match {
case x:SimpleType[_] => Cart.addProduct(x)
case _ => S.notice("Sorry not possible to add to Basket")
}
My main issue is that "Underscore" definition of the supplied type to SimpleType which causes type violation errors. I am currently not able to figure out how to do the wanted typing right. It would be great it someone could tell me where my error is and properbly explain to me how I work with typed traits correctly.
Thanks
I have a small Scala/Neo4j application that links people and topics through "skilledAt" and "interestedIn" relations. It has a REST/Json Api (using Scalatra) and I ran into a typical type-erasure problem when I wanted to add an "asJson" method to List[Person] and List[Topic]. I would like to implement different Json serialization behaviour for the different content types but of course the types get erased. The best I've been able to come up with so far is the following runtime trick:
implicit def topicsOrPeopleAsJson[T](list: List[T]) = new {
def asJson: String = {
list match {
case head :: tail if (head.isInstanceOf[Topic]) => topicsToJson(list.asInstanceOf[List[Topic]])
case head :: tail if (head.isInstanceOf[Person]) => peopleToJson(list.asInstanceOf[List[Person]])
case _ => "[]"
}
}
private def peopleToJson(people: List[Person]) = {
...
}
private def topicsToJson(topics: List[Topic]) = {
...
}
}
This works just fine but I was wondering whether there was a better solution, maybe something including type classes, a topic I'm not very familiar with (yet).
Use another level of implicit (this is typeclasses indeed):
trait ListToJsonConverter[T] {
def asJson(l: List[T]) : String
}
implicit object PeopleToJsonConverter extends ListToJsonConverter[Person] {...}
implicit object TopicToJsonConverter extends ListToJsonConverter[Topic] {...}
implicit object DefaultJsonConverter extends ListToJsonConverter[Any] {
def asJson(l: List[Any]) = "[]"
}
implicit def topicsOrPeopleAsJson[T](list: List[T])(implicit ev : ListToJsonConverter[T]) = new {
def asJson = ev.asJson(list)
}
This may not be exactly what you asked for however. The converter will be chosen at compile time. So if you call with a list of person which the compiler knows only as a List[Any], it will not work as expected.
Why not do it the OO way?
trait JSONable {
def toJSON:String
}
class Person
class Topics
implicit def persontoJSONable(p:Person) = new PersonSerializer(p)
implicit def topicToJSONable(t:Topic) = new PersonSerializer(t)
class PersonSerializer(p:Person) extends JSONable {
override def toJSON = {
//...
}
}
class TopicSerializer(t:Topic) extends JSONable {
override def toJSON = {
//...
}
}
def ListAsJSON[T <% JSONable](l:List[T]) = {
l.map(_.toJSON)
}