published | tags | ||||
---|---|---|---|---|---|
true |
|
在Scala中,我們要處理asynchronous computations的時候應該都知道有Future這個好用的東西,但Future monad常讓我在進行error handling的時候有點困擾,我本來的回傳值若是有"成功"或"失敗"兩種case的時候,我們可以用Scalaz的disjuction或是Scalactic的Or來處理,但是加上Future後的結果會變成:
published | tags | ||||
---|---|---|---|---|---|
true |
|
在Scala中,我們要處理asynchronous computations的時候應該都知道有Future這個好用的東西,但Future monad常讓我在進行error handling的時候有點困擾,我本來的回傳值若是有"成功"或"失敗"兩種case的時候,我們可以用Scalaz的disjuction或是Scalactic的Or來處理,但是加上Future後的結果會變成:
published | tags | ||||
---|---|---|---|---|---|
true |
|
之前一篇 [ScaVa->Scala] Scala中使用Reader Monad來實現Dependency Injection ,裡面提到了Scalaz中的Reader Monad,有Reader當然也要有個Writer呀!!
之前曾經寫過一篇 什麼是Monad? ,裡面提到了對於Monad的解釋,而今天進一步解釋這些在Functional Programming中常見到的詞:Functor, Applicative, Monad, Semigroup, Monoid。 透過放在一起比較,讓我們更清楚這些之間的差別與關係。
##Functor
在提到Functor之前,請先了解一下scala中map的作用,map可以讓你傳入一個function,而透過這個function是可以從F[A]轉換成F[B],這裡的F不管他(就是代表外面的包裝不會變),而裡面的A型態轉成B型態。
例如:
Shortener
trait is an interface that defines core functions of shortener which is shorter
& taller
.
trait Shortener {
def shorter(url:String)(implicit dbClient : DBClient, tracerInfo: TracerInfo) : String Or BaseException
def taller(short:String)(implicit dbClient : DBClient, tracerInfo: TracerInfo) : String Or BaseException
}
// Use Gists to store code you would like to remember later on | |
console.log(window); // log the "window" object to the console |
import java.io.{FileOutputStream, ByteArrayOutputStream, ByteArrayInputStream} | |
import java.util.zip.GZIPInputStream | |
import java.util.zip.GZIPOutputStream | |
import java.io._ | |
object GzipHelper { | |
implicit def StringGzipConvertor(str:String) = new { | |
def toGzipBytes(charset:String="UTF-8") = compress(str,charset) | |
def toGzipBytesString(charset:String="UTF-8") = new String(compress(str,charset).map(_.toChar)) |
val a : Option[String] = Some("abc") | |
if(a.isEmpty) | |
println("do something if a has value "+a.get) | |
else | |
println("do something if a is empty") |
case class HttpRequest(path:String, queryStrings:Map[String,List[String]]) { | |
def getPath() : String Or String = if(path.length>0) Good(path) else Bad("path cannot be empty.") | |
def getQueryStrings() : ((List[String], Int), String) Or Every[String] = { | |
validateKeyword(queryString.get("keyword")) zip validateNumber(queryString.get("number")) zip validateGender(queryString.get("gender")) | |
} | |
def validateKeyword(value:Option[List[String]]) : List[String] Or One[String] = { | |
if(value.isDefined && value.get.length>0) Good(value.get) else Bad(One("No keyword.")) | |
} | |
def validateNumber(value:Option[List[String]]) : Int Or One[String] = { | |
try{ |