1

我正在使用 Scalaz IO Monad 和 Stream 在 spoj.com 上寻找“生命、宇宙和一切”问题的解决方案。问题是从输入到输出重写小数字,并在读入数字 42 后停止处理输入。我创建了以下类:

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)
}

永无止境的循环按预期工作:

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

但是,当我希望它在数字 42 上完成时,它也没有完成:

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

我知道这段代码毕竟应该打印 42(与问题陈述相反),但我想简化示例代码。

我在哪里犯错?

4

1 回答 1

1

Stream.continually(EchoInt).sequence重复EchoInt无限次,所以你的程序基本上是一个无限循环。

你想要做的是在break你的循环中加入某种东西,它将分析每次迭代的输入并在输入等于 42 时停止循环。break函数式编程中没有(因为没有循环,只有递归),所以你根本不继续递归:

import scalaz.syntax.monad._

...

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

echoInts.unsafePerformIO()
于 2015-09-20T15:52:56.420 回答