Skip to content

Instantly share code, notes, and snippets.

@ardok
Last active December 28, 2015 04:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ardok/7440233 to your computer and use it in GitHub Desktop.
Save ardok/7440233 to your computer and use it in GitHub Desktop.
Box helper for Lift
import scalaz._
import Scalaz._
import xml.{Elem, NodeSeq}
import net.liftweb.util.CssSel
import net.liftweb.util.Helpers._
import net.liftweb.http.js.JsCmds.Noop
import net.liftweb.http.js.JsCmd
import net.liftweb.common.{Failure, Full, Box, Empty}
/**
* Example:
*
* import scalaz._
* import Scalaz._
*
*
* val str: Box[String] = Empty
* ~str // ""
*
* val str: Box[String] = Failure("failure")
* ~str // ""
*
* val ns: Box[NodeSeq] = Empty
* ~ns // NodeSeq.Empty
*
* val ns: Box[NodeSeq] = Empty
* ns | <lift:children>it failed!</lift:children> // output the xml
*
* val result: Box[String] = Full("")
* result >| S.notice("Successful") // don't care about result value if it's Full
*
* val str: String = null
* str.box // will be Empty
*
* `isTrueBox` and `isNotTrueBox` will be useful in a `for {} yield {}` situation
* Same case for `toBox` when you want to return a `Box` type in a `for yield` but the first `flatMap`
* happens to an `Option`. Hence, you can do `for { str <- optionStr.toBox ... } yield {}`
*
*/
object BoxHelper {
implicit val nodeSeqMonoid: Monoid[NodeSeq] = Monoid.instance(_ ++ _, NodeSeq.Empty)
implicit val listNodeSeqMonoid: Monoid[List[NodeSeq]] = Monoid.instance(_ ++ _, List(NodeSeq.Empty))
implicit val cssSelMonoid: Monoid[CssSel] = Monoid.instance(_ & _, "*" #> NodeSeq.Empty)
implicit val listCssSelMonoid: Monoid[List[CssSel]] = Monoid.instance(_ ++ _, List("*" #> NodeSeq.Empty))
implicit val elemMonoid: Monoid[Elem] = Monoid.instance((x, y) => <lift:children>{x}{y}</lift:children>, <lift:children></lift:children>)
implicit val jsCmdMonoid: Monoid[JsCmd] = Monoid.instance(_ & _, Noop)
implicit val throwableMonoid: Monoid[Throwable] =
Monoid.instance((x, y) => new Throwable(x.getMessage + "\n" + y.getMessage), new Throwable("Failure without exception"))
implicit final class RichBoxBoolean(boxBoolean: Box[Boolean]) {
def orFalse: Boolean = boxBoolean openOr false
def orTrue: Boolean = boxBoolean openOr true
}
implicit final class BoxZero[T: Monoid](a: Box[T]) {
/**
* Open the box or return the Zero value of that type
* @return value of the box or Zero value of that type
*/
def unary_~(implicit z: Monoid[T]): T = a openOr z.zero
/**
* Same like `unary_~`
*/
def orZero(implicit z: Monoid[T]): T = a openOr z.zero
}
implicit final class RichBox[T](a: Box[T]) {
/**
* Follow Scalaz `|`
* Alias for `openOr`
* @return value of the box or `default`
*/
def `|`(default: => T): T = a openOr default
/**
* Alias for `.map(_ => do_something)`
*/
def >|[B](f: => B): Box[B] = a.map(_ => f)
/**
* Alias for `openOrThrowException` with its exception message set
* @return the value of the box or exception throw
*/
def open: T = a.openOrThrowException("Trying to open a Failure / an Empty")
/**
* Alias for `openOrThrowException`
* @param exceptionMsg msg for exception
* @return the value of the box or exception throw
*/
def open(exceptionMsg: String): T = a.openOrThrowException(exceptionMsg)
/**
* This is the same as Scalaz tuple operator
* @return Full(tuple) of the values or Empty
*/
def tuple[B](b: => Box[B]): Box[(T, B)] =
a.toOption tuple b.toOption match {
case Some((x, y)) => Full((x, y))
case _ => Empty
}
/**
* Execute a function of `T => Any` if it's a `Full`
*/
def ifFull(map: T => Any): Any = a match {
case Full(f) => map(f)
case _ => Unit
}
/**
* Execute a function of `T => Any` if it's a `Failure`
*/
def ifFailure(map: Failure => Any): Any = a match {
case f @ Failure(_,_,_) => map(f)
case _ => Unit
}
/**
* Execute a function of `T => Any` if it's an `Empty`
*/
def ifEmpty(map: () => Any): Any = a match {
case Empty => map
case _ => Unit
}
}
implicit final class OptionToBox[T](o: Option[T]) {
/**
* Similar to `.toOption` from Box
* Alias for `Box` constructor
* @return a Box of the Option value that is passed in
*/
def toBox: Box[T] = Box(o)
}
implicit final class ToBox[T](s: T) {
/**
* Wrap any type into a Box() by using `Box !!`, hence using `legacyNullTest`
* `null` will be converted to Empty
* @return value wrapped in a Box (Full)
*/
def box: Box[T] = Box !! s
}
implicit final class BoxBoolean[T <: Boolean](a: Box[T]) {
/**
* Value of contained Boolean if it exists, false otherwise
* @return NonEmpty of the same value
*/
def isTrue: Boolean = a.exists(identity)
/**
* Check whether the value inside the Box is true
* @return the Box itself
*/
def isTrueBox: Box[Boolean] = a.filter(_ == true)
/**
* Check whether the value inside the Box is false
* @return the Box itself
*/
def isNotTrueBox: Box[Boolean] = a.filter(_ == false)
}
// extra for Java lovers (`null` boolean)
implicit def JavaBooleanToScala(x: java.lang.Boolean): Boolean = Option(x).map(_.booleanValue) getOrElse false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment