在Scalaz中组合IO和State Monad

时间:2015-05-13 19:28:54

标签: scala scalaz

我正在尝试使用scalaz中的State monad编写一个简单的程序,它将根据用户传入的输入修改某些状态。如何最好地完成。目前我有:

import scalaz._
import Scalaz._
import effect._
import IO._

def acc = for {
  i <- init
  _ <- modify{s: Int => 100}
  v <- readLn
  _ <- modify{s: Int => v}
} yield ()

抛出:

<console>:25: error: polymorphic expression cannot be instantiated to expected type;
 found   : [B]scalaz.effect.IO[B]
 required: scalaz.IndexedStateT[scalaz.Id.Id,Int,?,?]

1 个答案:

答案 0 :(得分:4)

你不能直接这样做,但monad变压器版本并不太可怕:

import scalaz._, Scalaz._, effect._, IO._

type IS[S, A] = StateT[IO, S, A]
type ISInt[A] = IS[Int, A]

val ms = MonadState[IS, Int]
import ms._

def acc = for {
  i <- init
  _ <- modify(s => 100)
  v <- readLn.liftIO[ISInt]
  _ <- modify(s => v.toInt)
} yield ()

这为您提供StateT[IO, Int, Unit],您可以使用IO转换为acc.exec(whatever)行动。

值得注意的是,您的代码可能会被清理一下 - 例如,init是不必要的,如果您扔掉,也可以使用put modify等中的论据。值得注意的是,实际上像IORef这样的东西在这里可能更实用。