一般来说,我在查找如何在"内部"monad中编写tailrecursive函数时遇到问题.这是一个简单的例子:
这是我写的一个小示例应用程序,以更好地理解Scala中的FP.首先,提示用户进入由7名玩家组成的团队.此函数以递归方式读取输入:
import cats.effect.{ExitCode, IO, IOApp}
import cats.implicits._
case class Player (name: String)
case class Team (players: List[Player])
/**
* Reads a team of 7 players from the command line.
* @return
*/
def readTeam: IO[Team] = {
def go(team: Team): IO[Team] = { // here I'd like to add @tailrec
if(team.players.size >= 7){
IO(println("Enough players!!")) >>= (_ => IO(team))
} else {
for {
player <- readPlayer
team <- go(Team(team.players :+ player))
} yield team
}
}
go(Team(Nil))
} …Run Code Online (Sandbox Code Playgroud) 几天来,我一直在围绕猫效应和IO.而且我觉得我对这种效果有一些误解,或者我只是错过了它的观点.
IO.shift?用IO.async?是IO.delay同步还是异步?我们可以用这样的代码创建一个通用的异步任务Async[F].delay(...)吗?或者当我们用unsafeToAsync或调用IO时发生异步unsafeToFuture?我很感激有些澄清任何一个,因为我没有理解猫效应文档对那些和互联网没有帮助...
为了快速清晰起见,对于那些想开始使用Scala FP库的人,他们正准备变得精通纯FP。
有人可以澄清一下Cats和Cats-Effects,Cats-Effects IO之间的区别/关系吗?最重要的是,Zio和Monix对此持何立场?最后,与ScalaZ 7/8有什么关系?
到目前为止,根据我所读的内容,可以根据可用的文档很好地结合使用的库,它们的作用是Cats,Cats-Effect和ZIO(可以与Cats-effects一起使用)?但是我不太清楚为什么,并且想为自己设定一条学习如何成为更好的FP程序员的良好途径,同时保持生产力,并且不必在开始选择之前完成“ Scala FP编程”。
我正在尝试将项目从 cats-effect 2 迁移到 cats-effect 3,我正在使用 doobie 与数据库交互。以前我可以ConnectionIO按照描述的IO那样升级,但是升级后我没有找到任何实现,如何使用 CE3 实现相同的效果?LiftIO[ConnectionIO]
我想组合多个IO应该并行独立运行的值.
val io1: IO[Int] = ???
val io2: IO[Int] = ???
Run Code Online (Sandbox Code Playgroud)
在我看来,我必须选择:
val parallelSum1: IO[Int] = for {
fiber1 <- io1.start
fiber2 <- io2.start
i1 <- fiber1.join
i2 <- fiber2.join
} yield i1 + i2
Run Code Online (Sandbox Code Playgroud)Parallel实例IO与parMapN(或它的兄弟姐妹等中的一种parTraverse,parSequence,parTupled等)
val parallelSum2: IO[Int] = (io1, io2).parMapN(_ + _)
Run Code Online (Sandbox Code Playgroud)不确定每种方法的优缺点,何时我应该选择其中一种方法.当抽象出效果类型IO(无标签 - 最终样式)时,这变得更加棘手:
def io1[F[_]]: F[Int] = ???
def io2[F[_]]: F[Int] = ???
def parallelSum1[F[_]: Concurrent]: F[Int] = for …Run Code Online (Sandbox Code Playgroud) import cats._
import cats.implicits._
trait Console[F[_]]{
def readInput() : F[Int]
def print(msg: String) : F[Unit]
}
class Foo {
def doFoo[F[_]: Monad](number: Int)(implicit C: Console[F]) : F[Unit] = {
C.readInput().flatMap{input =>
if (input == number) C.print("you won").map(_ => ())
else if (input > number) C.print("you guessed too high").flatMap(_ => doFoo(number))
else C.print("you guessed too low").flatMap(_ => doFoo(number))
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是我从编译器中得到了这个神秘的错误
cmd18.sc:5: ambiguous implicit values:
both value catsStdInstancesForList in trait ListInstances of type => cats.Traverse[List] with cats.Alternative[List] with cats.Monad[List] with …Run Code Online (Sandbox Code Playgroud) 当使用像Scala和的功能环境时cats-effect,是否应该使用效果类型来建模有状态对象的构造?
// not a value/case class
class Service(s: name)
def withoutEffect(name: String): Service =
new Service(name)
def withEffect[F: Sync](name: String): F[Service] =
F.delay {
new Service(name)
}
Run Code Online (Sandbox Code Playgroud)
构造不是容易犯错的,因此我们可以使用较弱的typeclass,例如Apply。
// never throws
def withWeakEffect[F: Applicative](name: String): F[Service] =
new Service(name).pure[F]
Run Code Online (Sandbox Code Playgroud)
我想所有这些都是纯粹的和确定性的。只是不是参照透明的,因为每次生成的实例都是不同的。那是使用效果类型的好时机吗?还是这里会有不同的功能模式?
我正在使用 Doobie,在我发现的示例中,它使用unsafeRunSync,例如:
sql"select name from country"
.query[String] // Query0[String]
.to[List] // ConnectionIO[List[String]]
.transact(xa) // IO[List[String]]
.unsafeRunSync // List[String]
.take(5) // List[String]
.foreach(println)
Run Code Online (Sandbox Code Playgroud)
在底层,该函数的实现如下:
final def unsafeRunSync(): A = unsafeRunTimed(Duration.Inf).get
Run Code Online (Sandbox Code Playgroud)
在文档中,我发现“请注意,此函数用于测试;它永远不应该出现在您的主线生产代码中!”。我想知道如果它unsafeRunSync在幕后使用这个功能,那么在生产中使用是否可以?
另外,如果不使用,如何设置执行超时unsafeRunTimed?
我正在尝试将Mules转换为 Cats Effect 3 (CE3)。由于它是一个缓存库,在它的测试中它需要(虚拟)时间来测试项目是否会过期。它目前正在大量使用cats.effect.laws.util.TestContext,它允许在不实际睡眠的情况下推进虚拟时钟tick。TestContextCE3 中不存在(据我所知),但我总是不愿意将sleep调用放入测试中。IO为这个特定案例滚动我自己的前景是一个令人生畏的前景。当然,这是人们更普遍的问题。但是,我无法TestContext在迁移指南中找到参考。
这种情况是否有已知的升级路径?
根据cats官方文档:https : //typelevel.org/cats-effect/typeclasses/liftio.html ,如果我们想把东西从IO提升到其他容器,你应该实现LiftIO trait,但示例明确运行unsafeRunXXX方法来获取出了效果,我想知道这是转型的唯一途径吗?