/ / Kombinácia Scalaz IO monad s Stream pre jednoduchý echo program pomocou metódy takeWhile - io, monads, scalaz, io-monad

Kombinácia Scalaz IO monad s Stream pre jednoduchý program echo pomocou metódy takeWhile - io, monads, scalaz, io-monad

Hľadám riešenie preVesmír a všetko “na stránkach spoj.com pomocou Scalaz IO Monad a Stream. Problémom je prepísať malé čísla zo vstupu na výstup a zastaviť spracovanie vstupu po prečítaní čísla 42. Vytvoril som nasledujúce triedy:

import scalaz._, effect._

def ReadInt: IO[Int] = IO {
readInt
}
def PrintInt(i: Int): IO[Unit] = IO {
println(i)
}
def EchoInt: IO[Int] = {
for {
i <- ReadInt
_ <- PrintInt(i)
} yield (i)
}

Nekonečná slučka funguje podľa očakávania:

scala> import Scalaz._
scala> Stream.continually(EchoInt).sequence.unsafePerformIO
12
22
32
42
52

Keď však chcem, aby to skončilo na čísle 42, nedokončí sa tiež:

scala> Stream.continually(EchoInt).sequence.map(_.takeWhile(_ != 42)).unsafePerformIO
12
22
32
42
52

Viem, že tento kód by mal napokon vytlačiť 42 (na rozdiel od vyhlásenia problému), ale chcel som príkladový kód zjednodušiť.

Kde sa mýlim?

odpovede:

1 pre odpoveď č. 1

Stream.continually(EchoInt).sequence opakovanie EchoInt nekonečné časy, takže váš program je v podstate nekonečná slučka.

Čo chcete urobiť, je dať nejaký druh break do vašej slučky, ktorá bude analyzovať vstup pri každej iterácii a zastaví slučku, ak sa vstup rovná 42. Nie je break vo funkčnom programovaní (pretože neexistujú slučky, iba rekurzia), takže rekurzia jednoducho nepokračujete:

import scalaz.syntax.monad._

...

def echoInts: IO[Unit] = {
for {
i <- EchoInt
_ <- echoInts.whenM(i != 42) // Break if i == 42
} yield ()
}

echoInts.unsafePerformIO()