1
votes

I've got a list monad List[Int]. I want to generate effects (Disjunction, and state) based on the values of the list. Here is my monad stack and the code to run the monad stack. My question is what should be proper way define checkNum so that I can generate the correct effects?

My expected output should
List(("", \/-(1), ("Error: 2", -\/(Throwable())), ("",\/-(3)), ("Error: 4", -\/(Throwable())))

import scalaz._
import Scalaz._

type EitherTH[F[_], A] = EitherT[F, Throwable,A]
type StateTH[F[_], A] = StateT[F, String, A]
type StateTList[A] = StateTH[List, A]
type EitherTStateTList[A] = EitherTH[StateTList, A]
val lst = List(1,2,3,4)

def checkNum(x:Int)(implicit ms:MonadState[EitherTStateTList, Int]) = if ((x%2)==0) {
  put(s"Error: $x")
  -\/(new Throwable())
}  else {
   put("")
   \/-(x)
}  

val prg = for {
  x <- lst.liftM[StateTH].liftM[EitherTH]
  // y <- checkNum(x).liftM[EitherTH]
} yield y 

prg.run("")
1
Working with > 2 monads is unwieldy in scala, try eff or emm.Reactormonk

1 Answers

0
votes

In my opinion checkNum should return a State[String, \/[Throwable,Int]]:

def checkNum0(x: Int): State[String, \/[Throwable,Int]] = if ((x%2)==0) {
  constantState(-\/(new Throwable()), s"Error: $x")
} else {
  constantState(\/-(x), "")
}

def checkNum1(x: Int): StateTList[\/[Throwable,Int]] = checkNum0(x).lift[List]

Then you can write your for-comprehension as:

val prg = for {
  x <- lst.liftM[StateTH].liftM[EitherTH]
  y <- EitherT(checkNum1(x))
} yield y

Output:

List(
  ("", \/-(1)),
  ("Error: 2", -\/(java.lang.Throwable)),
  ("", \/-(3)),
  ("Error: 4", -\/(java.lang.Throwable))
)