What's missing to get this working?
import scalaz._
import Scalaz._
val r = Some(1.0) |+| None
val r1 = None[Double] |+| Some(1.0)
I am getting the following:
Error:(4, 25) value |+| is not a member of Some[Double] lazy val r =
Some(1.0) |+| None
^
The problem is that a Monoid over Double is not lawful as the associativity rule can be invalidated in some cases by floating point arithmetic approximation. For this reason scalaz left that instance out of the main project and included it instead in the scalaz-outlaws one.
Include that library if you need to have an instance for Double but remember that there is a reason for this and consider your use case (e.g. if you are processing money transactions using floating point arithmetic you are probably doing something wrong).
Related
In the below two scenarios, I have flatMap function invoked on a list. In both the cases, the map portion of the flatMap function returns an array which has a iterator. In the first case, the code errors out where in the second case, it produces the expected result.
Scenario-1
val x = List("abc","cde")
x flatMap ( e => e.toArray)
<console>:13: error: polymorphic expression cannot be instantiated to expected type;
found : [B >: Char]Array[B]
required: scala.collection.GenTraversableOnce[?]
x flatMap ( e => e.toArray)
Scenario-2
val x = List("abc,def")
x flatMap ( e => e.split(",") )
res1: List[String] = List(abc, def) //Result
Can you please help why in the first case, it is not behaving as expected ?
I think the difference is that in scenario 1 you actually have a Array[B] where B is some yet-to-be-decided supertype of Char. Normally the compiler would look for an implicit conversion to GenTraversableOnce but because B is not yet known you run into a type inference issue / limitation.
You can help type inference by filling in B.
List("abc", "cde").flatMap(_.toArray[Char])
Or even better, you don't need flatMap in this case. Just call flatten.
List("abc", "cde").flatten
It is worth keeping in mind that Array is not a proper Scala collection so compiler has to work harder to first convert it to something that fits with the rest of Scala collections
implicitly[Array[Char] <:< GenTraversableOnce[Char]] // error (Scala 2.12)
implicitly[Array[Char] <:< IterableOnce[Char]] // error (Scala 2.13)
Hence because flatMap takes a function
String => GenTraversableOnce[Char]
but we are passing in
String => Array[Char]
the compiler first has to find an appropriate implicit conversion of Array[Char] to GenTraversableOnce[Char]. Namely this should be wrapCharArray
scala.collection.immutable.List.apply[String]("abc", "cde").flatMap[Char](((e: String) => scala.Predef.wrapCharArray(scala.Predef.augmentString(e).toArray[Char]((ClassTag.Char: scala.reflect.ClassTag[Char])))))
or shorter
List("abc", "cde").flatMap(e => wrapCharArray(augmentString(e).toArray))
however due to type inference reasons explained by Jasper-M, the compiler is unable to select wrapCharArray conversion. As Daniel puts it
Array tries to be a Java Array and a Scala Collection at the same
time. It mostly succeeds, but fail at both for some corner cases.
Perhaps this is one of those corner cases. For these reasons it is best to avoid Array unless performance or compatibility reasons dictate it. Nevertheless another approach that seems to work in Scala 2.13 is to use to(Collection) method
List("abc","cde").flatMap(_.to(Array))
scala> val x = List("abc","cde")
x: List[String] = List(abc, cde)
scala> x.flatMap[Char](_.toArray)
res0: List[Char] = List(a, b, c, c, d, e)
As the error mentions, your type is wrong.
In the first case, if you appy map not flatmap, you obtain List[Array[Char]]. If you apply flatten to that, you get a List[Char]
In the second case, if you appy map not flatmap, you obtain List[Array[String]]. If you apply flatten to that, you get a List[String]
I suppose you need to transform String to Char in your Array, in order to make it work.
I use Scala 2.13 and still have the same error.
Often I find myself passing a Seq with just one element to methods like this:
def myMethod(myList: Seq[Int]) = { ... }
Usually I do this like so:
myMethod(List(42))
But it occurs to me that this might not be the most elegant way, and if there's one thing about Scala that I love, it is its capability of blowing my mind by cutting down on characters used when I thought it impossible.
So, is there a shorter or more elegant representation of a single-item Seq than List(42)?
I can think of a couple worse options!
42 to 42
42 :: List()
Probably the shortest built-in way is to just use Seq companion object's apply and write
myMethod(Seq(42))
That apply function returns the default Seq implementation, that is A List and is therefore equivalent to using List(42).
I'm not sure there's any Seq implementation with a shorter name, but you can surely implement your own or simply import Seq (or List) while aliasing the name:
scala> import scala.collection.{Seq => S}
scala> S(42)
res0: Seq[Int] = List(3)
A shorter usage syntax may be obtained with this implicit,
implicit def SingletonSeq(i: Int) = Seq(i)
Hence
def myMethod(myList: Seq[Int]) = myList.size
myMethod(42)
res: 1
Looking at Haskell's Either Monad, there's a >>= function.
Prelude Map> let add100 = \x -> Right (x+100 :: Int)
Prelude Map> x
Right 5
Prelude Map> x >>= add100
Right 105
Prelude Map> let y = Left "..." :: Either String Int
Prelude Map> y >>= add100
Left "..."
However, why doesn't Scala's Either[A,B] have a flatMap, i.e. equivalent to >>= function?
scala> e
res5: Either[String,Int] = Right(1)
scala> e.
asInstanceOf fold isInstanceOf isLeft isRight
joinLeft joinRight left right swap
toString
Also, what's the meaning of left and right?
scala> e.left
res6: scala.util.Either.LeftProjection[String,Int] = LeftProjection(Right(1))
scala> e.right
res7: scala.util.Either.RightProjection[String,Int] = RightProjection(Right(1))
Either can't have a flatMap, because Either is not a monad. Haskell makes it into a monad by favoring one of the two types over the other, but there really is no justification to do so. Either means "this can be one of two types". Period. It does not give any preferential treatment to one of the two types.
If you use Either for error reporting, then it is true that you want it to be biased to one side, but that is only one usecase of many, and hardcoding a single special usecase into a general interface smells of bad design. And for that usecase, you might just as well use Try, which is basically a biased Either.
left and right return a projection of the Either, which is biased to one side.
However, note that the design and usability of Either has been debated very often, and it is indeed not exactly a shining beacon of good API design. Which is one of the reasons why Try and ScalaZ \/ exist.
You can either use fold which requires two functions, one for left and one for right, or use the right projection view:
val e: Either[String, Int] = Right(5)
def add100(i: Int): Either[String, Int] = Right(i + 100)
e.fold(identity, add100) // Right(105)
e.right.flatMap(add100) // Right(105)
So the projection views allow you to see an Either instance as something that will be mapped through the left or right type. This is explained in the Either scala-doc help file.
If you are familiar with Haskell, the ScalaZ library might be for you, it has its own 'either' abstraction called \/ (as described here).
Scala's Either type is unbiased. With types like Try, Future, etc, map and flatMap operate on the successful state, but with Either is this is not the case (though Right is often favored for success). If Either has no true successful state, which value should flatMap operate on? Left or Right? That's left up to you with projections.
left and right are the projections of Either, which are essentially biased versions of Either.
val test: Either[String, Int] = Right(1)
test.right.map(_ + 1) // Right-biased, will map the value to Right(2)
test.left.map(_ + 1) // Left-biased, will not operate on the value since it's `Right`, therefore returning Right(1) again.
Scala’s Either class was redesigned in Scala 2.12. Prior to 2.12, Either was not biased, and didn’t implement map and flatMap methods. As the image from the book shows, Either is redesigned in 2.12 to include those methods, so it can now be used in Scala for-expressions as shown.
https://alvinalexander.com/photos/scala-either-left-right-2.12-biased-map-flatmap/
In Scala 2.12 you can you e.g. this:
for {
right1 <- either1
right2 <- either2
} yield (righ1 + right2)
Alright, Scala has me feeling pretty dense. I'm finding the docs pretty impenetrable -- and worse, you can't Google the term "Scala ++:" because Google drops the operator terms!
I was reading some code and saw this line:
Seq(file) ++: children.flatMap(walkTree(_))
But couldn't figure it out. The docs for Seq show three things:
++
++:
++:
Where the latter two are over loaded to do.. something. The actual explanation in the doc says that they do the same thing as ++. Namely, add one list to another.
So, what exactly is the difference between the operators..?
++ and ++: return different results when the operands are different types of collection. ++ returns the same collection type as the left side, and ++: returns the same collection type as the right side:
scala> List(5) ++ Vector(5)
res2: List[Int] = List(5, 5)
scala> List(5) ++: Vector(5)
res3: scala.collection.immutable.Vector[Int] = Vector(5, 5)
There are two overloaded versions of ++: solely for implementation reasons. ++: needs to be able to take any TraversableOnce, but an overloaded version is provided for Traversable (a subtype of TraversableOnce) for efficiency.
Just to make sure:
A colon (:) in the end of a method name makes the call upside-down.
Let's make two methods and see what's gonna happen:
object Test {
def ~(i: Int) = null
def ~:(i: Int) = null //putting ":" in the tail!
this ~ 1 //compiled
1 ~: this //compiled
this.~(1) //compiled
this.~:(1) //compiled.. lol
this ~: 1 //error
1 ~ this //error
}
So, in seq1 ++: seq2, ++: is actually the seq2's method.
edited: As #okiharaherbst mentions, this is called as right associativity.
Scala function naming will look cryptic unless you learn a few simple rules and their precedence.
In this case, a colon means that the function has right associativity as opposed to the more usual left associativity that you see in imperative languages.
So ++: as in List(10) ++: Vector(10) is not an operator on the list but a function called on the vector even if it appears on its left hand-side, i.e., it is the same as Vector(10).++:(List(10)) and returns a vector.
++ as in List(10) ++ Vector(10) is now function called on the list (left associativity), i.e., it is the same as List(10).++(Vector(10)) and returns a list.
what exactly is the difference between the operators..?
The kind of list a Seq.++ operates on.
def ++[B](that: GenTraversableOnce[B]): Seq[B]
def ++:[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[Seq[A], B, That]): That
def ++:[B](that: TraversableOnce[B]): Seq[B]
As commented in "What is the basic collection type in Scala?"
Traversable extends TraversableOnce (which unites Iterator and Traversable), and
TraversableOnce extends GenTraversableOnce (which units the sequential collections and the parallel.)
Last night in responding to this question, I noticed the following:
scala> val foo: Option[Set[Int]] = Some(Set(1, 2, 3))
foo: Option[Set[Int]] = Some(Set(1, 2, 3))
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> foo.sequenceU
res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
That is, if foo is an optional set of integers, sequencing it returns a set of integers.
This isn't what I expected at first, since sequencing a F[G[A]] should return a G[F[A]] (assuming that F is traversable and G is an applicative functor). In this case, though, the Option layer just disappears.
I know this probably has something to do with some interaction between one of the supertypes of Set and the Unapply machinery that makes sequenceU work, and when I can find a few minutes I'm planning to work through the types and write up a description of what's going on.
It seems like a potentially interesting little puzzle, though, and I thought I'd post it here in case someone can beat me to an answer.
wow, yeah. Here's what I can surmise is happening. since Set doesn't have an Applicative of its own, we are getting the Monoid#applicative instance instead:
scala> implicitly[Unapply[Applicative, Set[Int]]].TC
res0: scalaz.Applicative[_1.M] forSome { val _1: scalaz.Unapply[scalaz.Applicative,Set[Int]] } = scalaz.Monoid$$anon$1#7f5d0856
Since Monoid is defined for types of kind * and applicative is defined for types of kind * -> *, the definition of Applicative in Monoid sorta wedges in an ignored type parameter using a type lambda:
final def applicative: Applicative[({type λ[α]=F})#λ] = new Applicative[({type λ[α]=F})#λ] with SemigroupApply...
Notice there that the type parameter α of λ is thrown away, so when Applicative#point is called, which becomes Monoid#zero, instead of it being a Monoid[Set[Option[Int]]] it is a Monoid[Set[Int]].
larsh points out that this has the interesting side-effect of alllowing sequenceU to be (ab)used as sum:
scala> List(1,2,3).sequenceU
res3: Int = 6