[英]Scala simplify nested monads
我有一些用Lift編寫的代碼。 基本上它的嵌套Box(類似monad to Option)。 如果可能的話,我想稍微簡化一下。 最好添加類型參數,這樣可以根據需要輕松更改為字符串或雙精度。 這是代碼
tryo(r.param("boolean parameter").map(_.toBoolean)).map(_.openOr(false)).openOr(false)
“tryo”是輔助函數,用於捕獲並在Box中包含結果,如果發生異常且r是Req對象。 “param”函數返回Box [String](來自請求參數)。 我想讓它適用於Int的String等等,如果可能的話,擺脫嵌套的map / openOr(你認為在Option類型中有getOrElse)。
Monad變形金剛?
那個sh * t的flatMap
!
r.param("boolean parameter").flatMap(tryo(_.toBoolean)).openOr(false)
或者,使用一個理解:
val result = for {
param <- r.param("boolean parameter")
bool <- tryo(param.toBoolean)
} yield bool
result openOr false
但這並不能解決你獲得不同類型的能力。 為此我會建議像:
def asOrDefault[T](input: Box[Any])(default: => T): T = input.flatMap(tryo(_.asInstanceOf[T])).openOr(default)
asOrDefault(r.param("any param"))(0)
這是未經測試的...另請注意, scala.util.control.Exception.allCatch.opt()
將返回一個Option
,就像tryo
返回一個Box
。
如果要抽象類型,則需要抽象默認值和字符串轉換:
case class Converter[T]( default: T, fromString: String => T )
然后為您的類型定義隱式實例:
implicit val intConverter = Converter[Int]( 0, _.toInt )
implicit val boolConverter = Converter[Boolean]( false, _.toBoolean )
最后,使用pr1001回答,使用隱式提供的轉換器值:
def asOrDefault[T](input: Box[String])(implicit conv: Converter[T]): T = input.flatMap(
s => tryo( conv.fromString(s))).openOr(conv.default)
編譯器將為您選擇適當的轉換器實例:
asOrDefault[Int]( input.param("some int param") )
asOrDefault[Boolean]( input.param("some boolean param") )
我在@ pr1001和@paradigmatic的基礎上進行了一些調整版本。
case class Converter[T]( fromString: String => T )
implicit val boolConverter = Converter(_.toBoolean)
implicit val intConverter = Converter(_.toInt)
def asOrDefault[T](input: Box[String], default: T)(implicit conv: Converter[T]): T =
input.flatMap( s => tryo(conv.fromString(s))).openOr(default)
在我的情況下使用:
def prettyPrint(implicit r: Req) = asOrDefault(r.param("prettyPrint"), false)
def maxResults(implicit r: Req): Int = asOrDefault(r.param("maxResults"), 20)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.