我有一些用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变形金刚?
答案 0 :(得分:6)
flatMap
sh * t!
r.param("boolean parameter").flatMap(tryo(_.toBoolean)).openOr(false)
或者,使用for comprehension:
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
一样。
答案 1 :(得分:3)
如果要抽象类型,则需要抽象默认值和字符串转换:
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") )
答案 2 :(得分:0)
我在@ 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)