मैं यह समझने की कोशिश कर रहा हूं कि एक कार्यक्रम को कैसे पुनर्गठित किया जाए जो मैंने पहले राज्य के बदलाव के अनुक्रम के रूप में लिखा था:
मेरे पास कुछ व्यावसायिक तर्क हैं:
type In = Long
type Count = Int
type Out = Count
type S = Map[Int, Count]
val inputToIn: String => Option[In]
= s => try Some(s.toLong) catch { case _ : Throwable => None }
def transition(in: In): S => (S, Out)
= s => { val n = s.getOrElse(in, 0); (s + (in -> n+1), n+1) }
val ZeroOut: Out = 0
val InitialState: S = Map.empty
इन के साथ मैं कुछ प्रारंभिक अवस्था (एक खाली नक्शा) में पारित करने के लिए एक कार्यक्रम का निर्माण करना चाहता हूं, स्टड से इनपुट पढ़ें , इसे रूपांतरित करें In
, राज्य संक्रमण चलाएं और वर्तमान स्थिति S
और आउटपुट Out
को stdout में आउटपुट करें ।
पहले, मैंने ऐसा कुछ किया होगा:
val runOnce = StateT[IO, S, Out](s => IO.readLn.map(inputToIn) flatMap {
case None => IO((s, ZeroOut))
case Some(in) => val (t, o) = transition(in)(s)
IO.putStrLn(t.toString) |+| IO.putStrLn(o.toString) >| IO((t, o))
})
Stream.continually(runOnce).sequenceU.eval(InitialState)
हालांकि, मैं वास्तव में यह देखने के लिए संघर्ष कर रहा हूं कि इस दृष्टिकोण (राज्य संक्रमण की एक धारा) को स्कैज-स्ट्रीम के साथ कैसे जोड़ा जाए । मैंने इसके साथ शुरुआत की:
type Transition = S => (S, Out)
val NoTransition: Transition = s => (s, 0)
io.stdInLines.map(inputToIn).map(_.fold(NoTransition)(transition))
इस प्रकार की है: Process[Task, Transition]
। मैं वास्तव में नहीं जानता कि वहाँ से कहाँ जाना है।
- मैं अपने "पास"
InitialState
और प्रोग्राम को कैसे चलाता हूं , अगलेS
चरण में इनपुट के रूप में प्रत्येक चरण में आउटपुट में फैल रहा हैS
? - मैं के मूल्यों कैसे मिलता है
S
औरOut
प्रत्येक चरण में है और उन्हें करने के लिए प्रिंट stdout (यह मानते हुए मैं उन्हें तार करने के लिए परिवर्तित कर सकते हैं)?
एकल-समझ का उपयोग करने की कोशिश में, मैं उसी तरह फंस गया:
for {
i <- Process.eval(Task.now(InitialState))
l <- io.stdInLines.map(inputToIn)
...
कोई भी मदद बहुत ही सराहनीय होगी!
मैं अब थोड़ा और आगे बढ़ गया हूं।
type In_ = (S, Option[In])
type Out_ = (S, Out)
val input: Process[Task, In_]
= for {
i <- Process.emit(InitialState)
o <- io.stdInLines.map(inputToIn)
} yield (i, o)
val prog =
input.pipe(process1.collect[In_, Out_]) {
case (s, Some(in)) => transition(in)(s)
}).to(io.stdOutLines.contramap[Out_](_.toString))
फिर
prog.run.run
यह काम नहीं करता है: ऐसा लगता है कि राज्य को धारा के माध्यम से पिरोया नहीं जा रहा है। बल्कि, प्रत्येक अवस्था में, प्रारंभिक अवस्था को पारित किया जा रहा है।
पॉल चिशानो ने सुझाव दिया कि किस दृष्टिकोण का उपयोग किया जाए process1.scan
। तो अब मैं यह करता हूं:
type In_ = In
type Out_ = (S, Out)
val InitialOut_ = (InitialState, ZeroOut)
val program =
io.stdInLines.collect(Function.unlift(inputToIn)).pipe(
process1.scan[In_, Out_](InitialOut_) {
case ((s, _), in) => transition(in)(s)
}).to(io.stdOutLines.contramap[Out_](_.shows))
यहां एक समस्या है: इस विशिष्ट उदाहरण में, मेरा Out
प्रकार एक मोनॉइड है , इसलिए मेरी प्रारंभिक अवस्था इसकी पहचान का उपयोग करके बनाई जा सकती है लेकिन आमतौर पर ऐसा नहीं हो सकता है। तब मैं क्या करूंगा? (मुझे लगता है कि मैं उपयोग कर सकता हूं Option
लेकिन ऐसा लगता है कि यह अनावश्यक है।)