scala - For-Comprehension Example with \/ and IO -


given following foo case class:

scala> case class foo(x: int) defined class foo 

i check if it's valid foo before constructing inside of validatefoo:

scala> def validatefoo(foo: foo): \/[string, foo] =                (if(foo.x > 0) foo.success[string]                else ("invalid foo").failure[foo]).disjunction validatefoo: (foo: foo)scalaz.\/[string,foo] 

lastly, f creates foo, , tries perform io action (example: save foo database).

scala> def f(x: foo): io[\/[string,int]] = {      |    foo <- validatefoo(x)      |    iofoo <- io { foo }      | } yield iofoo <console>:19: error: type mismatch;  found   : scalaz.effect.io[foo]  required: scalaz.\/[?,?]           iofoo <- io { foo }                 ^ <console>:18: error: type mismatch;  found   : scalaz.\/[string,nothing]  required: scalaz.effect.io[scalaz.\/[string,int]]           foo <- validatefoo(x)               ^ 

however, ran above issue when trying chain bind's in for-comprehension.

the problem, see it, proper return type io[\/[string, int]]. however, don't know how validate foo and handle in io monad for-comprehension.

you can't combine string \/ a , io[a] computations this—if desugared for-comprehension you'd see types don't work out.

if wanted to, use monad transformer compose 2 monads. suppose have following setup, example (which code, cleaned bit, , new method representing database operation):

import scalaz._, scalaz._, effect._  case class foo(x: int)  def validatefoo(foo: foo): string \/ foo =   (foo.x > 0) either foo or "invalid foo"  def processfoo(foo: foo): io[foo] = io {   println(foo)   foo } 

now can write following:

type iostringor[a] = eithert[io, string, a]  def f(x: foo): iostringor[foo] = {   foo <- eithert(validatefoo(x).point[io])   iofoo <- processfoo(foo).liftio[iostringor] } yield iofoo 

now can run eithert io action:

val ioaction: io[string \/ foo] = f(foo(10)).run 

that's how could use \/ , io in for-comprehension. it's pretty overkill in case, though. i'd write this:

def f(x: foo): io[string \/ foo] =   validatefoo(x).bitraverse(_.point[io], processfoo) 

this uses bitraverse instance \/ map function io on both sides of disjunction , turn whole thing inside out.


Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -