I just had a look into the cats library in scala, more specifically the State Monad.
As a toy example I wanted to create some logic that splits a potentially large string (the StringBuilder) and returns the split up String and the remaining StringBuilder:
object Splitter {
def apply(maxSize: Int, overlap: Int): State[StringBuilder, String] = State(
builder => {
val splitPoint = math.min(builder.size, maxSize + overlap)
(builder.drop(maxSize), builder.substring(0, splitPoint))
}
)
}
Running one step of the State monad works fine but I wanted to chain all the steps until the StringBuilder eventually is empty:
val stop = State.inspect((s: StringBuilder) => s.isEmpty)
Splitter(3, 2).untilM[Vector](stop).run(new StringBuilder("tarsntiars"))
However, this doesn't work as untilM is a member of the Monad trait and there are no implicit conversions in scope. What works is:
val monad = StateT.catsDataMonadForStateT[Eval, StringBuilder]
monad.untilM[List, String](Splitter(3, 2))(stop).run(new StringBuilder("tarsntiars"))
However, I think the shorter is much more readable so I am wondering why it doesn't work? Why does the usual MonadOps mechanism doesn't work here?
After SI-2712 was fixed, the Unapply workaround was removed from Cats: https://github.com/typelevel/cats/pull/1583. Now you need the -Ypartial-unification compiler flag (assuming you are using Scala 2.11 or 2.12) in order for State to be treated as a Monad.
Scalaz still has the Unapply machinery so your code should work with Scalaz without the compiler flag.
Related
So with this code the head and exists methods are not returning a Char but a String so i can't use any Char method.
implicit val mapTest: Map[String, Set[String]] = Map(
"foo" -> Set("foo")
)
val stringTest: String = "test"
//This don't compile
stringTest.head.isLetter
stringTest.exists(_.isLetter)
If i remove the implicit, it works fine. It works fine if i change the Map definition to Map[String, String], but using any Collection in the map makes is not compile.
Is there a way to make it work? I also tried defining the Char type after calling head but it still fails
Don't expose mapTest in implicit scope: as it offers .apply(key: String): Set[String] it's considered as an implicit conversion String => Set[String] .
Anyway implicit conversion should be defined/used with caution, due to readability drawbacks.
Using .head (or .get) is a code smell.
Implicit conversions may lead to seemingly magical changes to semantics of the code and loss of control by the developer, which your example nicely demonstrates. For this reason they are often discouraged and we are advised to find ways to refactor the code to not use them if at all possible.
If there is no way around it, consider moving the implicit conversion "out-of-scope" by wrapping it in another object like so
object FooImplicits {
implicit def mapTest: Map[String, Set[String]] = Map(
"foo" -> Set("foo")
)
}
and then try to avoid importing them at the top level, but instead import FooImplicits._ only where it is absolutely necessary.
Note that implicits are acceptable when defining typeclasses and extension methods.
in haskell I could do the following to a string
let f = sequence [id, reverse]
f "test"
I am at a bit of a loss how to approach this in a better method using Cats. I currently have something like
val f = List(fun1,fun2)
val data = "test"
f map {fun => fun(data)}
Is there an implementations of Sequence or SequenceU that can accomplish this using Cats?
It's more or less exactly the same, except that the syntax is a little different, you need some extra imports, and the generic version isn't as convenient since Scala's String isn't just an alias for a list of characters:
import cats.instances.function._, cats.instances.list._, cats.syntax.traverse._
val funcs: List[String => String] = List(identity, _.reverse)
val f = funcs.sequenceU
In Haskell sequence requires a Traversable instance for the outer type constructor of its argument, and a Monad instance for the inner type constructor. Cats's sequence is almost the same—Traversable is called Traverse (because the name Traversable is already taken by the standard library), and it requires an Applicative instance instead of Monad (which is a more accurate constraint—Haskell's sequence only requires a monad instance for historical reasons).
If you wanted you could just import cats.implicits._, but that brings in a lot of other stuff. The imports above provide the minimal type class instances and syntactic extensions you need.
You can use f, which is a String => List[String], like this:
scala> f("test")
res0: List[String] = List(test, tset)
Note that if you're on 2.12.1 and have the -Ypartial-unification compiler flag enabled, you can just write .sequence, not .sequenceU. Why you need the U on earlier Scala versions is a long story—see my blog post here for an explanation.
Having used a Scala library that liberally exposes the reliance on implicits to the caller, I had experienced friction around this mechanism, as Scala makes it quite hard at times to debug implicit arguments, and because there's quite a bunch of places Scala would fill in values for implicit arguments from. (I could almost relate to it as "implicits hell" at one time).
At one time in my coding, Scala "complained" an implicit value could not be matched whereas in fact there was a "collision" of implicit values each coming from a different import.
Regardless of that perceived brittleness, it may at times feel borderline to an abuse of the context design pattern.
Why does it make sense to have implicit parameters in Scala?
In what scenarios would you use them and how would you avoid trouble?
As I'm not sure the experimentation-curve and potential for other team members getting totally confused are worth it, could you possibly suggest other scala idioms for sharing context between a multitude of Scala functions?
This questions is not for a specific implementation at hand, hopefully it's still a good fit for this site.
Generally, using a common type as an implicit parameter is a bad idea.
def badIdea(n: Int)(implicit s: String) = s * n
It doesn't take much to imagine why: you'll get conflicting implicits for the same thing if anyone else adopts this policy. Better to avoid it.
But who really wants to manually stuff in a scala.concurrent.ExecutionContext manually every time it's needed (which is practically everywhere)?
So the key is: when you have something with a specialized type, especially if it's bookkeeping that might need to be overridden manually but mostly should just do the right thing, then use implicit parameters. (This usually covers type classes as well.)
Then what do you do if you really need a string? Well, wrap it (at least formally--here it's a value class so in some contexts it will just pass the string around):
class MyWrappedString(val underlying: String) extends AnyVal {}
implicit val myString = new MyWrappedString("bird")
def decentIdea(n: Int)(implicit mws: MyWrappedString) = mws.underlying * n
scala> decentIdea(2) // In the bush?
res14: String = birdbird
Or if you think some additional logic is helpful, write a wrapper that takes an extra type parameter:
class ImplicitWithValue[K,V](val value: V) {
// Any extra generic logic goes here
}
object ImplicitWithValue {
class ValuePart[K] {
def apply[V](v: V) = new ImplicitWithValue[K,V](v)
}
private val genericValuePart = new ValuePart[Any]
private def typedValuePart[K] = genericValuePart.asInstanceOf[ValuePart[K]]
def apply[K] = typedValuePart[K]
}
Then you can
trait Marker1
implicit val implicit1 = ImplicitWithValue[Marker1]("fish")
def goodIdea(n: Int)(implicit ms: ImplicitWithValue[Marker1, String]) = ms.value * n
scala> goodIdea(3)
res17: String = fishfishfish
Ok, this is is not another question about fundamental differences between vals & defs or functions and methods. I see that while this compiles:
val Extractor = new AnyRef { def unapply(s :String) => Some(s) }
val x = "hello" match { case Extractor(s) => s }
changing val Extractor to def Extractor breaks the code. Why is it so? It's a bit disappointing, as I hoped for complete trasnparency that would let me change the implementation from vals (generating methods anyway) to defs, or vice versa. I wonder what else can be done with one but not another?
I'm not sure I can supply an exhaustive list, but I can explain what's going on in this case.
Extractor has to be a stable identifier. See Section 8.1.8 of the Scala Language Specification. (A def is not stable; a val is.)
Stable identifiers have certain nice properties that allow them to be more simply computed and have greater optimization possibilities.
Does Scala provide a built-in class, utility, syntax, or other mechanism for converting (by wrapping) an Iterator with an Iterable?
For example, I have an Iterator[Foo] and I need an Iterable[Foo], so currently I am:
val foo1: Iterator[Foo] = ....
val foo2: Iterable[Foo] = new Iterable[Foo] {
def elements = foo1
}
This seems ugly and unnecessary. What's a better way?
Iterator has a toIterable method in Scala 2.8.0, but not in 2.7.7 or earlier. It's not implicit, but you could define your own implicit conversion if you need one.
You should be very careful about ever implicitly converting an Iterator into an Iterable (I normally use Iterator.toList - explicitly). The reason for this is that, by passing the result into a method (or function) which expects an Iterable, you lose control of it to the extent that your program might be broken. Here's one example:
def printTwice(itr : Iterable[String]) : Unit = {
itr.foreach(println(_))
itr.foreach(println(_))
}
If an Iterator were somehow implicitly convertible into an Iterable, what will the following would print?
printTwice(Iterator.single("Hello"))
It will (of course) only print Hello once. Very recently, the trait TraversableOnce has been added to the collections library, which unifies Iterator and Iterable. To my mind, this is arguably a mistake.
My personal preference is to use Iterator explicitly wherever possible and then use List, Set or IndexedSeq directly. I have found that I can rarely write a method which is genuinely agnostic of the type it is passed. One example:
def foo(trades: Iterable[Trade]) {
log.info("Processing %d trades", trades.toList.length) //hmmm, converted to a List
val shorts = trades.filter(_.side.isSellShort)
log.info("Found %d sell-short", shorts.toList.length) //hmmm, converted to a List again
//etc