2011-10-16 34 views
14

Tôi đang cố gắng tìm ra cách sử dụng StateT để kết hợp hai máy biến áp trạng thái State dựa trên nhận xét về câu trả lời Scalaz state monad examples của tôi.scalaz List [StateT] .sequence - không thể tìm thấy giá trị ngầm cho tham số n: scalaz.Applicative

Có vẻ như tôi rất gần nhưng tôi gặp sự cố khi cố gắng áp dụng 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) 
} 

Vì vậy, tôi đã như xa như có một StateT[StateMap, Random, Int] mà tôi có thể unwrap với các quốc gia bản đồ ngẫu nhiên và trống rỗng ban đầu:

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

Bây giờ tôi muốn tạo ra một danh sách những StateT và sử dụng sequence để tôi có thể gọi list.sequence ! new Random(1L) apply Map[Int,Int](). Nhưng khi thử điều này, tôi nhận được:

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

Bất kỳ ý tưởng nào? Tôi có thể sử dụng một số trợ giúp cho các căng cuối cùng - giả sử nó có thể.

+0

Tôi chỉ không hiểu tại sao bạn không sử dụng ngẫu nhiên của Scala. –

+0

@ DanielC.Sobral, Scala có một lớp học ngẫu nhiên ?! Oh yeah nó cũng sẽ hoạt động. Nó không phải là vật chất cho câu hỏi của tôi vì vậy tôi sẽ để lại 'java.util.Random'. – huynhjl

Trả lời

9

Ah nhìn vào số scalaz Monad source, tôi nhận thấy có một số implicit def StateTMonad xác nhận rằng StateT[M, A, x] là một đơn nguyên cho thông số loại x. Cũng monads là applicatives, đã được xác nhận bằng cách nhìn vào the definition of the Monad đặc điểm và bằng cách chọc trong 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] 

Vì vậy, đây đã cho tôi ý tưởng về việc xác định một tiềm ẩn Applicative[StT] để giúp trình biên dịch:

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

Điều đó đã làm điều này:

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) 
Các vấn đề liên quan