monads - How to compose functions that return Option[List] in Scala? -


suppose have 2 functions orders , order items:

 def getorders(): option[list[int]] = ... def getorderitems(orderid: int): option[list[int]] = ... 

note both functions return option[list] since each function may fail.

now option of list of order items follows:

  • return some[list] if both functions return some and
  • none if of them returns none.

i tried compose these functions for (see below) did not work.

 val allorderitems = {   orderids   <- getorders();   orderid    <- orderids;   orderitems <- getorderitems(orderid) } yield orderitems 

how can build function getallorderitems():option[list[int]] using functions getorders , getorderitems ?

you want able turn middle 2 layers of option[list[option[list[int]]]] inside out, can options , lists next each other. operation called sequencing, , it's provided scalaz:

import scalaz._, scalaz._  val items: option[list[int]] =   getorders.flatmap(_.map(getorderitems).sequence).map(_.flatten) 

you equivalently use traverse, combines map , sequence operations:

val items: option[list[int]] =   getorders.flatmap(_ traverse getorderitems).map(_.flatten) 

if don't want use scalaz, write own (less polymorphic) sequence:

def sequence[a](xs: list[option[a]]) = xs.foldright(some(nil): option[list[a]]) {   case (some(h), some(t)) => some(h :: t)   case _ => none } 

and then:

val items: option[list[int]] = getorders.flatmap(   orderids => sequence(orderids.map(getorderitems)) ).map(_.flatten) 

the monad transformation solution pretty straightforward (if you're willing use scalaz):

val items: option[list[int]] = (   {     orderid <- listt(getorders)     itemid  <- listt(getorderitems(orderid))   } yield itemid ).underlying 

the nice thing approach don't have think need flatten, sequence, etc.—the plain old monadic operations want.


Comments

Popular posts from this blog

google app engine - 403 Forbidden POST - Flask WTForms -

Android layout hidden on keyboard show -

Parse xml element into list in Python -