为了快速清晰起见,对于那些想开始使用Scala FP库的人,他们正准备变得精通纯FP。
有人可以澄清一下Cats和Cats-Effects,Cats-Effects IO之间的区别/关系吗?最重要的是,Zio和Monix对此持何立场?最后,与ScalaZ 7/8有什么关系?
到目前为止,根据我所读的内容,可以根据可用的文档很好地结合使用的库,它们的作用是Cats,Cats-Effect和ZIO(可以与Cats-effects一起使用)?但是我不太清楚为什么,并且想为自己设定一条学习如何成为更好的FP程序员的良好途径,同时保持生产力,并且不必在开始选择之前完成“ Scala FP编程”。
我在以下媒体上看到了这篇文章:https : //medium.com/@odomontois/tagless-unions-in-scala-2-12-55ab0100c2ff。我很难理解其中的一段代码。文章的完整源代码可以在这里找到:https : //github.com/Odomontois/zio-tagless-err。
代码是这样的:
trait Capture[-F[_]] {
def continue[A](k: F[A]): A
}
object Capture {
type Constructors[F[_]] = F[Capture[F]]
type Arbitrary
def apply[F[_]] = new Apply[F]
class Apply[F[_]] {
def apply(f: F[Arbitrary] => Arbitrary): Capture[F] = new Capture[F] {
def continue[A](k: F[A]): A = f(k.asInstanceOf[F[Arbitrary]]).asInstanceOf[A]
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的问题:
谢谢!
更新:
第一个问题:
根据规格,如果缺少上限,则假定为“任意”。因此,任意处理被视为任意,但是,它似乎无法与任意互换。
这样编译:
object Test {
type Arbitrary
def test(x: Any): Arbitrary = x.asInstanceOf[Arbitrary] …
Run Code Online (Sandbox Code Playgroud) 我有 2 个用 C# 和 Scala 编写的 deflate 函数,当使用相同的输入运行时,返回的字节数组在前导字节和尾随字节中存在差异(中间字节之间的差异是由无符号/有符号字节机制预期的) C# 和 Scala)。
\nScala 中的 Deflate 函数:
\nimport java.io.ByteArrayOutputStream\nimport java.util.zip.{Deflater, DeflaterOutputStream}\n\nimport zio._\n\n\nobject ZDeflater {\n val deflater = ZManaged.makeEffectTotal(new Deflater(Deflater.DEFLATED, true))(_.end)\n\n val buffer = ZManaged.fromAutoCloseable(ZIO.succeed(new ByteArrayOutputStream()))\n\n val stream = for {\n d <- deflater\n b <- buffer\n s <- ZManaged.fromAutoCloseable(ZIO.succeed(new DeflaterOutputStream(b, d, true)))\n } yield (b, s)\n\n def deflate(input: Array[Byte]): RIO[blocking.Blocking, Array[Byte]] = stream.use { case (buffer, stream) =>\n for {\n () <- blocking.effectBlocking(stream.write(input))\n () <- blocking.effectBlocking(stream.flush())\n result = buffer.toByteArray\n …
Run Code Online (Sandbox Code Playgroud) 我在 ZIO 应用程序中使用 Doobie,有时会出现死锁(应用程序完全冻结)。如果我仅在一个内核上运行我的应用程序,或者达到与数据库的最大并行连接数,就会发生这种情况。
我的代码看起来像:
def mkTransactor(cfg: DatabaseConfig): RManaged[Blocking, Transactor[Task]] =
ZIO.runtime[Blocking].toManaged_.flatMap { implicit rt =>
val connectEC = rt.platform.executor.asEC
val transactEC = rt.environment.get.blockingExecutor.asEC
HikariTransactor
.fromHikariConfig[Task](
hikari(cfg),
connectEC,
Blocker.liftExecutionContext(transactEC)
)
.toManaged
}
private def hikari(cfg: DatabaseConfig): HikariConfig = {
val config = new com.zaxxer.hikari.HikariConfig
config.setJdbcUrl(cfg.url)
config.setSchema(cfg.schema)
config.setUsername(cfg.user)
config.setPassword(cfg.pass)
config
}
Run Code Online (Sandbox Code Playgroud)
或者,我在 Hikari ( config.setLeakDetectionThreshold(10000L)
)上设置了泄漏检测参数,但出现泄漏错误不是由于处理数据库查询所花费的时间。
我知道我可以使用
import zio.Task
def zip3Par[A, B, C](a: Task[A], b: Task[B], c: Task[C]): Task[(A, B, C)] =
a.zipPar(b).zipWithPar(c) { case ((a, b), c) => (a, b, c) }
def zip4Par[A, B, C, D](a: Task[A], b: Task[B], c: Task[C], d: Task[D]): Task[(A, B, C, D)] =
zip3Par(a, b, c).zipWithPar(d) { case ((a, b, c), d) => (a, b, c, d) }
Run Code Online (Sandbox Code Playgroud)
并行执行 3 或 4 个任务,但如果有更优雅的解决方案,我会更受伤吗?
ZIO
不依赖于Cats
,因此它具有自己的执行sequence
操作的方法: ZIO.sequencePar
和ZIO.sequence
。
我尝试使用sequence
interop提供的Cats
,它的工作方式与ZIO.sequence
:
import zio._
import zio.interop.catz._
import cats.implicits._
val t1: Task[Int] = ???
val t2: Task[Int] = ???
val t3: Task[Int] = ???
val seq = List(t1,t2,t3).sequence // <-- t1,t2,t3 are executed sequentially
(new DefaultRuntime {}).unsafeRun(seq)
Run Code Online (Sandbox Code Playgroud)
我可以ZIO
将其sequence
视为ZIO.sequencePar
,这样我可以并行运行任务吗?
似乎ZIO
需要一些Traverse
for 的parallel 实现Cats
,但我找不到任何实现。
这是我的依赖项:
libraryDependencies += "dev.zio" %% "zio" % "1.0.0-RC10-1"
libraryDependencies += "dev.zio" %% "zio-interop-cats" …
Run Code Online (Sandbox Code Playgroud) 我有以下 ZIO 程序,其中包含两个永久运行的进程:
for {
..
numberProvider <- numberProvider(queue).fork // runs forever
numberService <- numberService(queue) // runs forever
..
} yield ()
Run Code Online (Sandbox Code Playgroud)
上面的代码有效,但我想知道这是否是好的做法。
有2个问题:
可以吗,在主程序上运行 2. 进程。或者它也应该是Fiber?
我join
最终是否必须使用 Fibers,即使它们永远运行,因此永远不会到达join
?
for {
..
numberProvider <- numberProvider(queue).fork // runs forever
numberService <- numberService(queue) // runs forever
..
_ <- numberProvider.join // join in any case
} yield ()
Run Code Online (Sandbox Code Playgroud)concurrency functional-programming scala for-comprehension zio
我有几个Booleans
我想测试,比如
assert(g8Exists, equalTo(true)) &&
assert(projectExists, equalTo(true)) &&
assert(testenvExists, equalTo(true)) ...
Run Code Online (Sandbox Code Playgroud)
如果一个失败,我得到的只是:
false did not satisfy equalTo(true)
Run Code Online (Sandbox Code Playgroud)
不知道哪条线失败了。有没有办法添加描述性的断言消息。例如:
assert(g8Exists, equalTo(true), "g8Exists")
Run Code Online (Sandbox Code Playgroud)
或首选:
assertTrue(g8Exists, "g8Exists")
Run Code Online (Sandbox Code Playgroud)
会导致
false did not satisfy equalTo(true) - g8Exists
Run Code Online (Sandbox Code Playgroud)
或者有没有更好的测试方法Booleans
?
scala.js 是否与 scala ZIO 一起使用?我想在 scala.js 中使用 scala ZIO 我只知道如何在普通应用程序中使用 scala ZIO 有谁知道如何在 scala.js 中使用它?
我想按顺序运行两个集成测试。如何在ZIO Test 中实现这一点?
这是套房:
suite("Undeploy a Package")(
testM("There is a Package") {
PackageDeployer.deploy(pckg) *> // first deploy
assertM(PackageUndeployer.undeploy(pckg), equalTo(StatusCode.NoContent))
},
testM(s"There is no Package") {
assertM(PackageUndeployer.undeploy(pckg), equalTo(StatusCode.NotFound))
})
Run Code Online (Sandbox Code Playgroud)
ZIO Test并行运行这两个测试。有没有办法强制它们按顺序运行?
zio ×10
scala ×9
concurrency ×2
zio-test ×2
c# ×1
cats-effect ×1
deadlock ×1
doobie ×1
hikaricp ×1
java ×1
scala-cats ×1
scala.js ×1
scalaz ×1