Last active
December 15, 2020 13:45
-
-
Save holgergp/37f84740d7b958f40890 to your computer and use it in GitHub Desktop.
Some fiddling with map, flatMap and foldLeft on Collections, Strings and Option. Trying to understand the generic monadic approach
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object flatMapTest { | |
import scala.util.{ Try, Success, Failure } | |
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet | |
val intList = 1 :: 2 :: 5 :: Nil //> intList : List[Int] = List(1, 2, 5) | |
intList.map(x => x * 2) //> res0: List[Int] = List(2, 4, 10) | |
//intList.flatMap(x=>x*2) //type mismatch; found : Int required: scala.collection.GenTraversableOnce[?] | |
intList.foldLeft(0)((x, y) => x + y) //> res1: Int = 8 | |
val stringList = "eins" :: "zwei" :: "drei" :: Nil | |
//> stringList : List[String] = List(eins, zwei, drei) | |
stringList.map(x => x.reverse) //> res2: List[String] = List(snie, iewz, ierd) | |
stringList.flatMap(x => x.reverse) //> res3: List[Char] = List(s, n, i, e, i, e, w, z, i, e, r, d) | |
stringList.foldLeft("")((x, y) => x + y) //> res4: String = einszweidrei | |
val optionList = Some("Eins") :: None :: Some("Zwei") :: Nil | |
//> optionList : List[Option[String]] = List(Some(Eins), None, Some(Zwei)) | |
def optionMatcher(x: Option[String]): String = x match { case Some(t) => t case None => "" } | |
//> optionMatcher: (x: Option[String])String | |
def optionMatcherToOption(x: Option[String]): Option[String] = x match { case Some(t) => Some(t.reverse) case None => None } | |
//> optionMatcherToOption: (x: Option[String])Option[String] | |
optionList.map(x => optionMatcherToOption(x)) //> res5: List[Option[String]] = List(Some(sniE), None, Some(iewZ)) | |
optionList.flatMap(x => x match { case Some(t) => t case None => "" }) | |
//> res6: List[Char] = List(E, i, n, s, Z, w, e, i) | |
optionList.flatMap(x => x match { case Some(t) => Some(t.reverse) case None => None }) | |
//> res7: List[String] = List(sniE, iewZ) | |
optionList.flatMap(x => x match { case Some(t) => Some(t.reverse) case None => None }) | |
//> res8: List[String] = List(sniE, iewZ) | |
optionList.foldLeft(Some(""))((x, y) => Some(optionMatcher(y))) | |
//> res9: Some[String] = Some(Zwei) | |
val simpleOption = Some("simple") //> simpleOption : Some[String] = Some(simple) | |
simpleOption.map(x => x) //> res10: Option[String] = Some(simple) | |
//simpleOption.flatMap(x=>x) //type mismatch; found : String required: Option[?] | |
simpleOption.flatMap(x => Some(x)) //> res11: Option[String] = Some(simple) | |
simpleOption.foldLeft(Some(""))((x, y) => Some(y)) | |
//> res12: Some[String] = Some(simple) | |
val noneOption = None //> noneOption : None.type = None | |
noneOption.map(x => x) //> res13: Option[Nothing] = None | |
noneOption.flatMap(x => x) //> res14: Option[Nothing] = None | |
noneOption.foldLeft(Some(""))((x, y) => Some(y))//> res15: Some[String] = Some() | |
def manageByteArray(x: Array[Byte]) = Option(x) //> manageByteArray: (x: Array[Byte])Option[Array[Byte]] | |
val futureSimulator = Option(Array(12.toByte, 15.toByte)) | |
//> futureSimulator : Option[Array[Byte]] = Some([B@5dfcfece) | |
futureSimulator.flatMap(x => manageByteArray(x))//> res16: Option[Array[Byte]] = Some([B@5dfcfece) | |
val futureSimulator2 = Some(Array(12.toByte, 15.toByte)) | |
//> futureSimulator2 : Some[Array[Byte]] = Some([B@23ceabc1) | |
futureSimulator2.flatMap(x => manageByteArray(x)) | |
//> res17: Option[Array[Byte]] = Some([B@23ceabc1) | |
val futureSimulator3 = None //> futureSimulator3 : None.type = None | |
futureSimulator3.flatMap(x => manageByteArray(x)) | |
//> res18: Option[Array[Byte]] = None | |
//http://stackoverflow.com/questions/27715863/flatmap-implementation-in-scala | |
//auf Some("String") und Some(Some("String") testen | |
Some("test").map(x => x) //> res19: Option[String] = Some(test) | |
Some("test").flatMap(x => Option(x)) //> res20: Option[String] = Some(test) | |
Some(Some("test")).map(x => x) //> res21: Option[Some[String]] = Some(Some(test)) | |
Some(Some("test")).flatMap(x => Option(x)) //> res22: Option[Some[String]] = Some(Some(test)) | |
Some(None).flatMap(x => Option(x)) //> res23: Option[None.type] = Some(None) | |
Some(None).map(x => x) //> res24: Option[None.type] = Some(None) | |
def doSideEffects(x: Option[String]): Option[String] = { | |
println("Da!") | |
Some("") | |
} //> doSideEffects: (x: Option[String])Option[String] | |
def doSideEffects2(x: String): Option[String] = { | |
println("Da!") | |
Some(x) | |
} //> doSideEffects2: (x: String)Option[String] | |
Some(None).flatMap(x => doSideEffects(x)) //> Da! | |
//| res25: Option[String] = Some() | |
None.flatMap(x => doSideEffects2(x)) //> res26: Option[String] = None | |
Some("test").flatMap(x => doSideEffects2(x)) //> Da! | |
//| res27: Option[String] = Some(test) | |
Some("test").getOrElse(None) //> res28: java.io.Serializable = test | |
None.getOrElse(None) //> res29: None.type = None | |
Some("test").map(x => doSideEffects2(x)) //> Da! | |
//| res30: Option[Option[String]] = Some(Some(test)) | |
Some("test").map(x => doSideEffects2(x)).getOrElse(None) | |
//> Da! | |
//| res31: Option[String] = Some(test) | |
None.map(x => doSideEffects2(x)) //> res32: Option[Option[String]] = None | |
None.map(x => doSideEffects2(x)).getOrElse(None)//> res33: Option[String] = None | |
} |
In that case flatMap "flattens" the String list. It treats String as List of chars. The type definition of flatMap says that the resulting type of the function fed into flatMap has to suffice the type scala.collection.GenTraversableOnce[?] as you see in line 6. There the flatMap for List[Int] fails. String seems to implement GenTraversableOnce
I interpret GenTraversableOnce as "behave like a baseline list"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
stringList.flatMap(x => x.reverse) == List(s, n, i, e, i, e, w, z, i, e, r, d) is a little bit strange. I can imagine that at x.reverse there happened an autoboxing from String to List[Char].