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

Android layout hidden on keyboard show -

google app engine - 403 Forbidden POST - Flask WTForms -

c - Why would PK11_GenerateRandom() return an error -8023? -