2011-10-16 25 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) 
相关问题