2011-10-16 24 views
14

我想弄清楚如何使用StateT結合兩個State狀態轉換器的基礎上我的Scalaz state monad examples答案的評論。scalaz List [StateT] .sequence - 無法找到參數n的隱式值:scalaz.Applicative

看起來我非常接近,但我在試圖申請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] 
        ^

任何想法?我可以用最後一段時間的一些幫助 - 假設它是可能的。

+0

我只是不明白你爲什麼不使用Scala的隨機。 –

+0

@ DanielC.Sobral,斯卡拉有一個隨機類?!哦,是的,它會工作得很好。這對我的問題不是重要的,所以我將離開'java.util.Random'。 – huynhjl

回答

9

啊看着scalaz Monad source,我注意到有一個implicit def StateTMonad確認StateT[M, A, x]是類型參數x的monad。此外單子是applicatives,這是通過觀察the definition of the Monad特質,並通過在REPL戳證實:

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

scala> implicitly[Monad[StT]] 
res2: scalaz.Monad[StT] = [email protected] 

因此,這給了我定義的隱含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) 
相關問題