14

Scalaz ステート モナドの例の回答へのコメントに基づいて、StateT2 つのステート トランスフォーマーを組み合わせる方法を見つけようとしています。State

私は非常に近いようですが、申請しようとしたときに問題が発生しましたsequence

import scalaz._
import Scalaz._
import java.util.Random

val die = state[Random, Int](r => (r, r.nextInt(6) + 1))

val twoDice = for (d1 <- die; d2 <- die) yield (d1, d2)

def freqSum(dice: (Int, Int)) = state[Map[Int,Int], Int]{ freq =>
  val s = dice._1 + dice._2
  val tuple = s -> (freq.getOrElse(s, 0) + 1)
  (freq + tuple, s)
}

type StateMap[x] = State[Map[Int,Int], x]

val diceAndFreqSum = stateT[StateMap, Random, Int]{ random =>
  val (newRandom, dice) = twoDice apply random
  for (sum <- freqSum(dice)) yield (newRandom, sum)
}

だから私はStateT[StateMap, Random, Int]、最初のランダムで空のマップ状態でアンラップできるものを持っているところまで行きました:

val (freq, sum) = diceAndFreqSum ! new Random(1L) apply Map[Int,Int]()
// freq: Map[Int,Int] = Map(9 -> 1)
// sum: Int = 9

StateTここで、それらのリストを生成して使用sequenceし、 を呼び出せるようにしたいと思いますlist.sequence ! new Random(1L) apply Map[Int,Int]()。しかし、これを試してみると、次のようになります。

type StT[x] = StateT[StateMap, Random, x]
val data: List[StT[Int]] = List.fill(10)(diceAndFreqSum)
data.sequence[StT, Int]

//error: could not find implicit value for parameter n: scalaz.Applicative[StT]
          data.sequence[StT, Int]
                       ^

何か案が?可能であれば、最後のストレッチに多少の助けを借りることができます。

4

1 に答える 1

9

ああ、scalaz Monad sourceを見て、型パラメータ x のモナドでimplicit def StateTMonadあることを確認するがあることに気付きました。StateT[M, A, x]また、モナドはアプリカティブであり、トレイトの定義をMonad見て、REPL を突き刺すことで確認されました。

scala> implicitly[Monad[StT] <:< Applicative[StT]]
res1: <:<[scalaz.Monad[StT],scalaz.Applicative[StT]] = <function1>

scala> implicitly[Monad[StT]]
res2: scalaz.Monad[StT] = scalaz.MonadLow$$anon$1@1cce278

Applicative[StT]したがって、これにより、コンパイラを支援するために暗黙を定義するというアイデアが得られました。

type StT[x] = StateT[StateMap, Random, x]
implicit val applicativeStT: Applicative[StT] = implicitly[Monad[StT]]

それはトリックをしました:

val data: List[StT[Int]] = List.fill(10)(diceAndFreqSum)
val (frequencies, sums) =
  data.sequence[StT, Int] ! new Random(1L) apply Map[Int,Int]()

// frequencies: Map[Int,Int] = Map(10 -> 1, 6 -> 3, 9 -> 1, 7 -> 1, 8 -> 2, 4 -> 2)
// sums: List[Int] = List(9, 6, 8, 8, 10, 4, 6, 6, 4, 7)
于 2011-10-16T07:02:26.700 に答える