【问题标题】:How do I define a function for a Monad Stack of State, Disjunction, and List?如何为 Monad Stack of State、Disjunction 和 List 定义函数?
【发布时间】:2017-03-19 17:58:31
【问题描述】:

我有一个列表单子List[Int]。我想根据列表的值生成效果(析取和状态)。这是我的 monad 堆栈和运行 monad 堆栈的代码。我的问题是什么应该是正确的方法来定义 checkNum 以便我可以产生正确的效果?

我的预期输出应该是
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("")

【问题讨论】:

  • 在 scala 中使用 > 2 个 monad 很麻烦,试试 eff 或 emm。

标签: scala scalaz monad-transformers


【解决方案1】:

在我看来checkNum 应该返回一个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]

那么你可以把你的理解写成:

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

输出:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 2011-05-07
    相关资源
    最近更新 更多