मुझे लगता है, scalaz 7.0.x और निम्नलिखित आयात (scalaz 6.x के लिए जवाब इतिहास पर नज़र डालें):
जहां
S
प्रकार है
import scalaz._
import Scalaz._
राज्य प्रकार State[S, A]
के रूप में परिभाषित किया गया है राज्य और A
मूल्य को सजाए जाने वाले प्रकार का प्रकार है।
// Create a state computation incrementing the state and returning the "str" value
val s = State[Int, String](i => (i + 1, "str"))
एक प्रारंभिक मूल्य पर राज्य गणना चलाने के लिए::
// start with state of 1, pass it to s
s.eval(1)
// returns result value "str"
// same but only retrieve the state
s.exec(1)
// 2
// get both state and value
s(1) // or s.run(1)
// (2, "str")
राज्य समारोह कॉल के माध्यम से पिरोया जा सकता है बुनियादी वाक्यविन्यास एक राज्य मान बनाने के लिए State[S, A]
समारोह का उपयोग करता है। Function[A, B]
के बजाय ऐसा करने के लिए, Function[A, State[S, B]]]
परिभाषित करें।
def TwoDice() = for {
r1 <- dice()
r2 <- dice()
} yield (r1, r2)
// start with a known seed
TwoDice().eval(new Random(1L))
// resulting value is (Int, Int) = (4,5)
यहाँ एक और उदाहरण है: State
समारोह ...
import java.util.Random
def dice() = State[Random, Int](r => (r, r.nextInt(6) + 1))
फिर for/yield
वाक्य रचना कार्यों की रचना करने के लिए किया जा सकता का उपयोग करें। TwoDice()
राज्य गणना के साथ एक सूची भरें।
val list = List.fill(10)(TwoDice())
// List[scalaz.IndexedStateT[scalaz.Id.Id,Random,Random,(Int, Int)]]
State[Random, List[(Int,Int)]]
प्राप्त करने के लिए अनुक्रम का उपयोग करें। हम एक प्रकार उपनाम प्रदान कर सकते हैं।
type StateRandom[x] = State[Random,x]
val list2 = list.sequence[StateRandom, (Int,Int)]
// list2: StateRandom[List[(Int, Int)]] = ...
// run this computation starting with state new Random(1L)
val tenDoubleThrows2 = list2.eval(new Random(1L))
// tenDoubleThrows2 : scalaz.Id.Id[List[(Int, Int)]] =
// List((4,5), (2,4), (3,5), (3,5), (5,5), (2,2), (2,4), (1,5), (3,1), (1,6))
या हम sequenceU
उपयोग कर सकते हैं जो प्रकार यह निष्कर्ष निकाल देगा:
val list3 = list.sequenceU
val tenDoubleThrows3 = list3.eval(new Random(1L))
// tenDoubleThrows3 : scalaz.Id.Id[List[(Int, Int)]] =
// List((4,5), (2,4), (3,5), (3,5), (5,5), (2,2), (2,4), (1,5), (3,1), (1,6))
उपरोक्त सूची में रकम की आवृत्ति की गणना करने के State[Map[Int, Int], Int]
साथ एक और उदाहरण। freqSum
फेंकता और गणना आवृत्तियों की गणना की गणना करता है।
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)
}
अब पार का उपयोग tenDoubleThrows
से अधिक freqSum
लागू करने के लिए। traverse
map(freqSum).sequence
के बराबर है।
type StateFreq[x] = State[Map[Int,Int],x]
// only get the state
tenDoubleThrows2.copoint.traverse[StateFreq, Int](freqSum).exec(Map[Int,Int]())
// Map(10 -> 1, 6 -> 3, 9 -> 1, 7 -> 1, 8 -> 2, 4 -> 2) : scalaz.Id.Id[Map[Int,Int]]
या अधिक संक्षेप traverseU
का उपयोग कर प्रकार का अनुमान लगाने के द्वारा:
tenDoubleThrows2.copoint.traverseU(freqSum).exec(Map[Int,Int]())
// Map(10 -> 1, 6 -> 3, 9 -> 1, 7 -> 1, 8 -> 2, 4 -> 2) : scalaz.Id.Id[Map[Int,Int]]
ध्यान दें कि क्योंकि State[S, A]
StateT[Id, S, A]
के लिए एक प्रकार का अन्य नाम है, tenDoubleThrows2 समाप्त होता है Id
के रूप में आपके द्वारा लिखा गया जा रहा है। मैं copoint
का उपयोग इसे List
प्रकार में बदलने के लिए करता हूं।
संक्षेप में, ऐसा लगता है कि राज्य का उपयोग करने की कुंजी राज्य को संशोधित करने वाले फ़ंक्शन को वापस करने और वास्तविक परिणाम मूल्य वांछित कार्य करने के लिए है ... अस्वीकरण: मैंने कभी भी उत्पादन कोड में state
का उपयोग नहीं किया है, बस एक इसके लिए महसूस करो।
@ziggystar टिप्पणी पर अतिरिक्त जानकारी
मैं stateT
का उपयोग कर किया जा सकता है किसी और दिखाई देते हैं, StateFreq
या StateRandom
संयुक्त गणना प्रदर्शन करने के लिए संवर्धित किया जा सकता कोशिश कर रहा पर छोड़ दिया। क्या मैं बजाय पाया गया कि दो राज्य ट्रांसफार्मर की संरचना इस तरह जोड़ा जा सकता है है:
def stateBicompose[S, T, A, B](
f: State[S, A],
g: (A) => State[T, B]) = State[(S,T), B]{ case (s, t) =>
val (newS, a) = f(s)
val (newT, b) = g(a) apply t
(newS, newT) -> b
}
यह g
पहला राज्य ट्रांसफार्मर का परिणाम लेने और एक राज्य ट्रांसफार्मर लौटने एक एक पैरामीटर समारोह किया जा रहा है पर प्रतिपादित है। उसके बाद निम्न काम करेगा:
def diceAndFreqSum = stateBicompose(TwoDice, freqSum)
type St2[x] = State[(Random, Map[Int,Int]), x]
List.fill(10)(diceAndFreqSum).sequence[St2, Int].exec((new Random(1L), Map[Int,Int]()))
'राज्य' मोनड नहीं है, जो "राज्य ट्रांसफार्मर" नहीं है? और एक दूसरे प्रश्न के रूप में: क्या पासा रोलिंग और एक एकल राज्य मोनड में संक्षेप को गठबंधन करने के लिए कुछ अच्छा तरीका है? आप दो monads दिए गए कैसे करेंगे? – ziggystar
@ ज़िगगीस्टार, तकनीकी रूप से 'स्टेटफ्रैक' और 'स्टेटरैंडम' मोनैड हैं। मुझे नहीं लगता कि 'राज्य [एस, एक्स]' एक मोनड ट्रांसफॉर्मर है क्योंकि 'एस' को मोनाड होने की आवश्यकता नहीं है। गठबंधन करने के लिए एक अच्छे तरीके के लिए, मैं भी सोच रहा हूँ। मुझे कुछ भी स्पष्ट रूप से आसानी से उपलब्ध नहीं दिख रहा है। हो सकता है कि 'स्टेट टी' मदद कर सके लेकिन मुझे अभी तक यह पता नहीं लगा है। – huynhjl
मैंने "मोनैड ट्रांसफार्मर" नहीं लिखा लेकिन "राज्य ट्रांसफार्मर"। 'राज्य [एस, एक्स]' ऑब्जेक्ट्स में एक राज्य नहीं है बल्कि बाद में परिवर्तन होता है। यह सिर्फ इतना है कि मुझे लगता है कि नाम कम भ्रमित चुना जा सकता है। यह आपके उत्तर के बारे में कुछ नहीं है लेकिन स्कालज़ के बारे में है। – ziggystar