猫效应有什么作用IO.suspend以及为什么有用?有文档,但并不完全清楚。
该文档给出了以下用例:
import cats.effect.IO
def fib(n: Int, a: Long, b: Long): IO[Long] =
IO.suspend {
if (n > 0)
fib(n - 1, b, a + b)
else
IO.pure(a)
}
Run Code Online (Sandbox Code Playgroud)
举个例子,为什么我要使用上面的函数,而不是下面的类似函数?
import cats.effect.IO
import scala.annotation.tailrec
@tailrec
def fib(n: Int, a: Long, b: Long): IO[Long] =
if (n > 0)
fib(n -1, b, a + b)
else
IO.pure(a)
Run Code Online (Sandbox Code Playgroud) 我知道,一般来说,关于决定要建模什么效果,有很多话要说。这个讨论是在 Scala 函数式编程中关于 IO 的章节中介绍的。
\n尽管如此,我还没有读完这一章,我只是从头到尾地浏览了一遍,然后才和 Cats IO 一起阅读。
\n与此同时,我在工作中遇到了一些需要很快交付的代码的情况。\n它依赖于一个与突变有关的 Java 库。该库是很久以前开始的,由于遗留原因,我没有看到它们发生变化。
\n无论如何,长话短说。实际上,将任何变异函数建模为 IO 是封装变异 Java 库的可行方法吗?
\n准备好建立一个模型,改变模型而不是创建一个新模型。例如,我会将 jena 与 gremlin 进行对比,gremlin 是一个基于图形数据的功能库。
\ndef loadModel(paths: String*): Model =\n paths.foldLeft(ModelFactory.createOntologyModel(new OntModelSpec(OntModelSpec.OWL_MEM)).asInstanceOf[Model]) {\n case (model, path) \xe2\x87\x92\n val input = getClass.getClassLoader.getResourceAsStream(path)\n val lang = RDFLanguages.filenameToLang(path).getName\n model.read(input, "", lang)\n }\nRun Code Online (Sandbox Code Playgroud)\n那是我的 scala 代码,但是网站中记录的 java api 看起来像这样。
\n// create the resource\nResource r = model.createResource();\n\n// add the property\nr.addProperty(RDFS.label, model.createLiteral("chat", "en"))\n .addProperty(RDFS.label, model.createLiteral("chat", "fr"))\n .addProperty(RDFS.label, model.createLiteral("<em>chat</em>", true));\n\n// …Run Code Online (Sandbox Code Playgroud) 我的结果如下:
EitherT[Future, IllegalStateException, Result]
Run Code Online (Sandbox Code Playgroud)
如何转换为 Future[Result] ?让 Future 因 IllegalStateException 失败?我知道我可以像 resultT.value 那样获取 Future[Either[Exception, Res]] 并转换它,但也许有更简单的方法。
我知道这完全是一个无意义的问题,但由于我对编程技能的文盲,这个问题浮现在我的脑海中。使用 Cats 和 scalaz,以便我们可以像 Haskell 那样以纯函数式编程方式在 Scala 中进行编码。但为了实现这一目标,我们需要在我们的项目中额外添加这些库。最终,为了使用它们,我们需要用它们的对象和函数来包装我们的代码。它是添加额外代码和依赖项的东西。我不知道这些是否会在内存中创建更大的对象。这些都让我思考。所以我的问题是:如果我使用 cats/scalaz ,我会面临任何性能问题,例如更多内存消耗吗?或者如果我的应用程序需要性能,我应该避免这些吗?
Ref[F, A]我正在尝试在两个并发流之间共享。下面是实际场景的简化示例。
class Container[F[_]](implicit F: Sync[F]) {
private val counter = Ref[F].of(0)
def incrementBy2 = counter.flatMap(c => c.update(i => i + 2))
def printCounter = counter.flatMap(c => c.get.flatMap(i => F.delay(println(i))))
}
Run Code Online (Sandbox Code Playgroud)
在主函数中,
object MyApp extends IOApp {
def run(args: List[String]): IO[ExitCode] = {
val s = for {
container <- Ref[IO].of(new Container[IO]())
} yield {
val incrementBy2 = Stream.repeatEval(
container.get
.flatTap(c => c.incrementBy2)
.flatMap(c => container.update(_ => c))
)
.metered(2.second)
.interruptScope
val printStream = Stream.repeatEval(
container.get
.flatMap(_.printCounter)
)
.metered(1.seconds) …Run Code Online (Sandbox Code Playgroud) 我在DSL中使用monad和comprenhension工作.由于我的客户端不知道Scala我试图隐藏这么多语法.到目前为止我有这个DSL
(for {
* <- Given("A message", message(path = "esb", version = TWO))
* <- And("With version 2.0", *)
* <- And("I make esb return 300", *)
* <- When("I make a request", *)
* <- Then("The return code is 500", *)
} yield ()).foldMap(scenario)
Run Code Online (Sandbox Code Playgroud)
这比使它们实现scalaTest要好得多,但这仍然可以吓到它们.
有没有办法隐藏使用隐式u其他机制的for/yield而只是离开DSL?
问候.
我有以下代码:
import cats._
import cats.Functor
object StudyIt {
def main(args: Array[String]): Unit = {
val one: Int = 1
val a = Functor[Id].map(one)(_ + 1)
println(a)
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,map期望的类型Id[Int],但我只是过去Int到map,为什么它是可能的吗?
我是FS2的新手,需要有关设计的一些帮助。我正在尝试设计一个流,该流将从底层提取块InputStream直到结束。这是我尝试过的:
import java.io.{File, FileInputStream, InputStream}
import cats.effect.IO
import cats.effect.IO._
object Fs2 {
def main(args: Array[String]): Unit = {
val is = new FileInputStream(new File("/tmp/my-file.mf"))
val stream = fs2.Stream.eval(read(is))
stream.compile.drain.unsafeRunSync()
}
def read(is: InputStream): IO[Array[Byte]] = IO {
val buf = new Array[Byte](4096)
is.read(buf)
println(new String(buf))
buf
}
}
Run Code Online (Sandbox Code Playgroud)
程序将打印第一个块。这是合理的。但是我想找到一种方法来“发出信号”在哪里停止阅读以及在哪里停止。我的意思是继续打电话read(is)直到结束。有办法实现吗?
我也尝试过,repeatEval(read(is)) 但它会一直读下去……我之间需要一些东西。
我有一个非常大val s: List[Int] = //...,一个功能f: Int => Boolean和一个功能transform: Int => Int.
问题:我想创造另一个List[Int],使得所有元素e: Int的的s: List[Int],这样f(e) = true与更换transform(e).
我看了一下cats-mtl FunctorEmpty(坚持函数编程风格),但它似乎不适用于我的情况.也许某些cats/ scalaz数据结构在这里有用吗?还是其他任何方式?
我是Cats的新手,我不知道如何克服这种情况.在下面的代码中:
class Example[F[_]] {
import cats._
import cats.data._
import cats.syntax.all._
def saveAll(list: List[String])(implicit M: Monad[F]): F[List[String]] = {
val result: List[F[String]] =
list.map(saveOne)
}
def saveOne(s: String)(implicit M: Monad[F]): F[String] = s"Saved $s".pure[F]
}
Run Code Online (Sandbox Code Playgroud)
如何result在saveAll函数中转换变量以确保它与预期的返回类型匹配?
谢谢.