2011-10-16 4 views
14

Próbuję dowiedzieć się, jak użyć StateT, aby połączyć dwa transformatory stanu State na podstawie komentarza na moją odpowiedź Scalaz state monad examples.scalaz Lista [StateT] .sequence - nie można znaleźć niejawnej wartości dla parametru n: scalaz.Applicative

Wygląda na to, że jestem bardzo blisko, ale mam problem podczas próby zastosowania 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) 
} 

Więc mam w miarę posiadania StateT[StateMap, Random, Int] że mogę rozpakować z początkowych losowych i pustych stanów mapy:

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

Teraz chciałbym, aby wygenerować listę tych StateT i używać sequence dzięki czemu mogę zadzwonić pod numer list.sequence ! new Random(1L) apply Map[Int,Int](). Ale próbując tego, otrzymuję:

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] 
        ^

Masz pomysł? Mogę skorzystać z pomocy na ostatnim odcinku - zakładając, że jest to możliwe.

+0

Po prostu nie rozumiem, dlaczego nie używasz Losu Scali. –

+0

@ DanielC.Sobral, Scala ma klasę Losowe ?! O tak, to by działało równie dobrze. To nie jest istotne dla mojego pytania, więc opuści "java.util.Random". – huynhjl

Odpowiedz

9

Ah patrząc na scalaz Monad source, zauważyłem, że był implicit def StateTMonad, który potwierdza, że ​​StateT[M, A, x] jest monadą dla parametru typu x. Również monady są applicatives, który został potwierdzony przez patrząc na the definition of the Monad cechy i grzebie w 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] 

Więc to dało mi pomysł definiowania niejawny Applicative[StT] pomóc kompilatora:

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

To zadziałało:

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) 
Powiązane problemy