Scalaz List [StateT].sequence - не удалось найти неявное значение для параметра n: scalaz.Applicative
Я пытаюсь понять, как использовать StateT
для объединения двух трансформаторов состояния State
на основе комментариев к моим примерам монады штата Scalaz.
Кажется, я очень близко, но у меня возникла проблема при попытке применить 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]
^
Любая идея? Я могу использовать некоторую помощь для последнего растяжения - если это возможно.
Ответы
Ответ 1
Ah, глядя на источник сканаза Монада, я заметил, что существует 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] = [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)