Reputation: 37435
Recently I stumbled upon some code that shouldn't have worked but did. This is a simplified illustration:
val l=List(1,2,3,4,5)
def isEven(i:Int):Option[Int] = if (i%2==0) Some(i) else None
for {elem <- l
even <- isEven(elem)
} yield even
That will produce List(2,4)
and might be no surprise to Scala developers.
But it shouldn't work given that List is monadic and should be of this form:
class M[A] {
def flatMap[B](f:A => M[B]):M[B]
def map[B](f:A => B):M[B]
}
Following this definition, every element of a chain of monadic operations must belong to the same monad. Map transforms elements within the context of the monad and flatMap
must 'trap' free elements into the monad.
In the example above, we have this desugarized representation:
l.flatMap(elem => isEven(elem))
which is of type: List[Int].flatMap[Int](f:Int => Option[Int])
and does not conform to the monadic definition.
The correct form of isEven
should have been:
def isEven(i:Int):List[Int] = if (i%2==0) List(i) else Nil
Looking into the scala-docs, it turns out that the reason that List
and Option
can be combined in a for comprehension in Scala, is that the flatMap
on List
is defined as flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): List[B]
and that allows for any traversable instance to be 'flatmapped' over. Option
is traversable, Set
, Seq
, and many others are too.
I'm left wondering: What are the consequences of this broader definition of flatMap
.
Are there cases that one should be aware/beware of?
Upvotes: 2
Views: 278
Reputation: 39577
The signature you have listed is the notorious "use case", not the method signature, aka the "full signature".
def flatMap[B, That](f: (A) ⇒ GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That
You can build any target for which there is a CanBuildFrom
.
The question is quite broad; I'm not sure the list of consequences has been catalogued.
Is the Scala 2.8 collections library a case of "the longest suicide note in history"?
The attempt to do so in the space of one talk.
Or for example:
https://stackoverflow.com/a/17377859/1296806
Upvotes: 2