This question already has answers here:
How can I chain implicits in Scala?
(3 answers)
Closed 8 years ago.
A simple example:
class A
class B
class C
object testobject {
val a = new A
implicit def b(a:A):B = new B
implicit def c(b:B) = new C
val b:B = a
val c:C = a
}
The last line doesn't compile. We have A=>B and B=>C implicit conversions defined but that doesn't infer A=>C.
It would be really nice to be able to have layers of implicit conversions work.
My particular problem. too long to post fully is actually from a web framework. I want to do something like:
A => Secure[A] => Format[A]
with the following
implicit def secure[A](a:A):Secure[A] = ???
implicit def format[A](sec:Secure[A]):Format[A] = ???
So I want to handle security and formatting through implicit magic, and only secured outputs can be formatted.
Has anybody found any tricks to make this, or something like this work?
This question is answered quite well here:
How can I chain implicits in Scala?
In short Scala does not chain implicit conversions, it only looks for direct conversion A => B. However, using additional implicit parameters the desired effect can be achieved.
Related
This question already has answers here:
Scalaz pipe operator connected with a list method
(2 answers)
Closed 4 years ago.
I find myself writing Scala programs more often recently.
I like to program in a style that often uses long method chains, but sometimes the transformation you want to apply is not a method of the object you want to transform. So I find myself defining:
class Better[T] (t: T){
def xform[U](func: T => U) = func(t)
}
implicit def improve[T](t: T) = new Better(t)
This allows my to write the chains I want, such as
val content = s3.getObject(bucket, key)
.getObjectContent
.xform(Source.fromInputStream)
.mkString
.toInt
Is there any similar facility already in the standard library? If so, how should I have discovered it without resorting to StackOverflow?
It's not the standard library, but it might be "standard enough": with Cats, you should be able to write something like
val content =
s3
.getObject(bucket, key)
.getObjectContent
.pure[Id].map(Source.fromInputStream)
.mkString
.toInt
where pure[Id] wraps the input value into the do-nothing Id monad, and then passes it as argument to Source.fromInputStream.
EDIT: This does not seem to work reliably. If the object already has a method map, then this method is called instead of Id.map.
Smaller example (just to demonstrate the necessary imports):
import cats.Id
import cats.syntax.applicative._
import cats.syntax.functor._
object Main {
def square(x: Int) = x * x
def main(args: Array[String]): Unit = {
println(42.pure[Id].map(square))
}
}
However, writing either
val content =
Source
.fromInputStream(
s3
.getObject(bucket, key)
.getObjectContent
)
.mkString
.toInt
or
val content =
Source
.fromInputStream(s3.getObject(bucket, key).getObjectContent)
.mkString
.toInt
does not require any extra dependencies, and frees you both from the burden of defining otherwise useless case classes, and also from the burden of reindenting your code every time you rename either content or s3.
It also shows how the expressions are actually nested, and what depends on what - there is a reason why the vast majority of mainstream programming languages of the past 50 years have a call-stack.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
scala: adding a method to List?
I struggle to formulate what I'm trying to do, but the code example should be pretty straightforward. If anyone knows a better way to phrase it, you are free to edit the title. :)
trait DiceThrow {
list: List[Int] => // something like this??
def yatzee = list.filter(_ == list.head).length >= 5
}
object Main extends App {
val aThrow = List(4,4,4,4,4) with DiceThrow
aThrow.yatzee // => true is what I want
}
So I want the aThrow: List[Int] to have some extra methods, like knowing whether it's a yatzee or not. This is just one example I made up where adding some extra methods to e.g. a List could be useful.
Is this possible somehow? Or is there another approach that's more the scala way? I believe it's possible with implicit conversion(?)(they're still pretty "magic" to me), but that seems unnecessarily dirty this use-case?
You can use enrich (pimp) my library pattern:
class DiceList(list: List[Int]) {
def yatzee = list.filter(_ == list.head).length >= 5
}
implicit def list2DiceList(list: List[Int]) = new DiceList(list)
In scala 2.10 it could be simplified with implicit classes:
implicit class DiceList(list: List[Int]) {
def yatzee = list.filter(_ == list.head).length >= 5
}
Then you could use it like:
object Main extends App {
val aThrow = List(4,4,4,4,4)
aThrow.yatzee // => true
}
I'm using a library that gives me the following (relations can be implicitly converted to nodes):
class Relation[A,B]
class Node[A,B](r: Relation[A,B])
implicit def relation2node[A,B](r: Relation[A,B]) = new Node(r)
I'm extending Relation for my own use:
class XRelation[A] extends Relation[A,Int]
Relations/XRelations are meant to be subclassed:
class User extends XRelation[Int]
Now, I also define my own Helper methods like GET, designed to work with any Node and anything that converts to Node:
class Helper[A,B](n: Node[A,B]) { def GET {} }
// note: this is the only way I know of to make the next example work.
implicit def xx2node2helper[A,B,C[_,_]](x: C[A,B])(implicit f: C[A,B] => Node[A,B]) = new Helper(x)
So this example works:
new Relation[Int,Int]().GET
And if I add another implicit conversion:
// don't understand why this doesn't work for the previous example
// but works for the next example
implicit def x2node2helper[A,B,C](x: C)(implicit f: C => Node[A,B]) = new Helper(x)
I can also make the following conversion work:
new XRelation[Int]().GET
But this doesn't work:
new User().GET
Sadly, that fails with:
error: No implicit view available from Sandbox3.User => Sandbox3.Node[A,B]
Can anyone make sense of all this and explain how to get the last example to work? Thanks in advance.
Update: I know you can just introduce implicit conversions from Relation, but I'm asking to (1) figure out how to do this without having to introduce implicits from every single type that could possibly implicitly convert to Node, and (2) to solidify my understanding of implicits.
implicit def nodeLike2Helper[R, C <: R](r:C)(implicit f: R => Node[_,_]) = {
new Helper(r)
}
Just as the error message indicates, User does not have implicit conversion to Node. But it's super-super-class Relation has. So you just give the right bounds to type parameters.
FYI, there is a syntax sugar <% for view bounds, so the above code can be shorter:
implicit def nodeLike2Helper[R <% Node[_,_], C <: R](r:C) = {
new Helper(r)
}
The scala resolution only goes one super class deep when checking if User matches the type pattern C[_,_]. You can fix this by doing away with the pattern in the following code.
implicit def x2node2helper[A,B](x: Relation[A,B])(implicit f: Relation[A,B] => Node[A,B]) = new Helper(x)
And if the implicit relation2node is in scope for the definition of x2node2helper then it can be written
implicit def x2node2helper[A,B](x: Relation[A,B]) = new Helper(x)
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How can I chain implicits in Scala?
Can Scala apply multiple implicit conversions in one expression?
Consider this simple example:
case class Wrapper(s: String)
case class WrapperWrapper(w: Wrapper)
implicit def string2Wrapper(s: String) = Wrapper(s)
implicit def wrapper2WrapperWrapper(w: Wrapper) = WrapperWrapper(w)
// implicit conversation --> w = string2Wrapper("w")
val w: Wrapper = "w"
// implicit conversation --> ww = wrapper2WrapperWrapper(w)
val ww: WrapperWrapper = w
// does NOT compile!
// ideally --> sad = wrapper2WrapperWrapper(string2Wrapper("ww"))
val sad: WrapperWrapper = "ww"
Is there any way to get the "double" conversion in the last line to work?
I can help things along by defining another implicit like:
implicit def string2WrapperWrapper(s:String) = wrapper2WrapperWrapper(s)
but it seems like that shouldn't be necessary...
I'm afraid I don't have a concise reference to hand (the answer is scattered through 6.26 and chapter 7 of The Scala Language Specification), but the answer is no.
This is due to practicality - double implicit conversions would square the number of possible conversions available, greatly increasing the chance of collisions and making it harder to work out exactly what would happen with a given conversion.
It's not ideal that you have to declare the String to WrapperWrapper conversion yourself; but given how rarely you need to do this in practice, compared to the potential confusion of double implicits, I do consider it the lesser of two evils.
You can coerce the sequence of conversions fairly concisely:
scala> val sad: WrapperWrapper = ("ww": Wrapper)
sad: WrapperWrapper = WrapperWrapper(Wrapper(ww))
As explained by #Andrzej Doyle, two conversions at a time magnifies the risk of accidental conversions happening and so it is dissallowed.
I'd like an extractor to implicitly convert its parameters, but it doesn't seem to work. Consider this very simple case:
case class MyString(s: String) {}
implicit def string2mystring(x: String): MyString = new MyString(x)
implicit def mystring2string(x: MyString) = x.s
object Apply {
def unapply(s: MyString): Option[String] = Some(s)
}
But I'm not able to use it as I would expect:
val Apply(z) = "a" // error: scrutinee is incompatible with pattern type
Can anyone explain why it fails to convert the parameter from String to MyString? I would expect it to call string2mystring("a") on the fly. Clearly I could work around the issue by saying val Apply(y) = MyString("a"), but it doesn't seem like I should have to do that.
Note: This question is similar to this one, but 1) that one doesn't really have a good answer for why this is happening, 2) the example is more complex than it needs to be.
Implicit conversions are not applied when pattern matching. That's not a bug or a problem with your code, it's simply a design decision of the creators of Scala.
To fix it, you should write another extractor that accepts a String — which in turn can call your implicit conversion.
Alternatively, you can try with a view bound, which seems to work as well, and will also work if you later define other implicit conversions to MyString:
object Apply {
def unapply[S <% MyString](s: S): Option[String] = Some(s.s)
}