在一名程序员刚刚学习函数式编程并完成在线 Scala 猫练习的背景下,以下结果似乎令人费解:
import cats._
import cats.implicits._
object Foo {
def main(args: Array[String]): Unit =
println(Foldable[List].fold(List(None, Option("two"), Option("three"))))
//Some("twothree")
println(Foldable[List].foldK(List(None, Option("two"), Option("three"))))
//Some("two")
}
Run Code Online (Sandbox Code Playgroud)
我可以遵循 for 的示例fold,但不能遵循 for 的示例foldK。FoldK 的文档说:
此方法与 Fold 相同,只是我们使用通用幺半群 (
MonoidK[G]) 来获取Monoid[G[A]]实例。
我不明白这种差异如何导致上面看到的行为,其中列表中的第三个元素 ( Option("three")) 被“忽略” foldK。
有人可以解释一下吗?
我有一个简单的 IO 操作序列,暂停 5 秒。
implicit val timer = IO.timer(ExecutionContext.global)
def doSth(str: String): IO[Unit] = IO(println(str))
def greeting(): IO[Unit] =
doSth("Before timer.") *>
Timer[IO].sleep(5 second) *>
doSth("After timer")
val a = greeting().unsafeRunAsyncAndForget()
Run Code Online (Sandbox Code Playgroud)
如何使计时器没有ExecutionContext.global,IOApp或固定线程数量ExecutionContext.global?
在 Connect4 游戏中:
我的想法是:
这种想法正确吗?
假设以上是正确的,以下哪一项是正确的?
我赞成第二种选择,对我来说更有意义。
我可以用这种方式堆叠这些 monads (State, IO) 吗?
我正在尝试使用 Cats 数据类型 Ior 来累积使用服务的错误和成功(可能返回错误)。
def find(key: String): F[Ior[NonEmptyList[Error], A]] = {
(for {
b <- service.findByKey(key)
} yield b.rightIor[NonEmptyList[Error]])
.recover {
case e: Error => Ior.leftNel(AnotherError)
}
}
def findMultiple(keys: List[String]): F[Ior[NonEmptyList[Error], List[A]]] = {
keys map find reduce (_ |+| _)
}
Run Code Online (Sandbox Code Playgroud)
我的困惑在于如何组合错误/成功。我正在尝试使用 Semigroup combine(中缀语法)进行组合,但没有成功。有一个更好的方法吗?任何帮助都会很棒。
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
def mapMergeMonoid[K, V](V: Monoid[V]): Monoid[Map[K, V]] = new Monoid[Map[K, V]] {
override def op(a1: Map[K, V], a2: Map[K, V]): Map[K, V] =
(a1.keySet ++ a2.keySet).foldLeft(zero) {
(acc, k) => acc.updated(k, V.op(a1.getOrElse(k, V.zero), a2.getOrElse(k, V.zero)))
}
override def zero: Map[K, V] = Map[K, V]()
}
Run Code Online (Sandbox Code Playgroud)
据我所知,我可以用这个 Monoid 连接 2 个 Map。但我无法理解,如何使用它。我必须放入(V: Monoid[V])参数以使用op方法之后并放置2张地图。
我创建了两个版本的服务。第一个使用Futures,另一个使用ZIO效果。
我有一个简单的方法,使用Future结果效果:
def get(id: String)(implicit executionContext: ExecutionContext): Future[Data]
Run Code Online (Sandbox Code Playgroud)
我还有一些其他版本使用ZIO[SomeEnv, SomeError, Data]:
def get(id: String): ZIO[SomeEnv, SomeError, Data]
Run Code Online (Sandbox Code Playgroud)
现在,我需要创建某种适配器,它将从一个版本或另一个版本返回数据:
def returnDataFromServiceVersion(version: Int) : ??? = {
if(version == 1) futureService.get(...)
else zioService.get(...)
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是返回类型。我不知道如何转换ZIO为未来或Future转换ZIO为具有共同的返回类型。我尝试使用ZIO.fromFuture{...}ortoFuture()但没有帮助。我的问题是 - 如何创建此returnDataFromServiceVersion方法以将其与这两种服务一起使用?我需要在这里有共同的返回类型。
或者也许有另一种方法可以解决这个问题?
我有一个fs2.Stream可能会遇到错误的无限。我想跳过这些错误而不做任何事情(可能是日志)并继续流式传输更多元素。例子:
//An example
val stream = fs2.Stream
.awakeEvery[IO](1.second)
.evalMap(_ => IO.raiseError(new RuntimeException))
Run Code Online (Sandbox Code Playgroud)
在这种特殊情况下,我想获得无限fs2.Stream的Left(new RuntimeException)发射每一秒。
有一种Stream.attempt方法可以生成在遇到第一个错误后终止的流。有没有办法跳过错误并继续拉取更多元素?
这IO.raiseError(new RuntimeException).attempt通常不会起作用,因为它需要在流管道组合的所有位置尝试所有效果。
在 Cats 2.1.x 中,类型类实例被引入范围内import cats.implicits._
scala> import cats.Show
import cats.Show
scala> Show[Int].show(42)
<console>:13: error: could not find implicit value for parameter instance: cats.Show[Int]
Show[Int].show(42)
^
scala> import cats.implicits._
import cats.implicits._
scala> Show[Int].show(42)
res1: String = 42
Run Code Online (Sandbox Code Playgroud)
然而在 Cats 2.2.0中,它无需import cats.implicits._例如
scala> import cats.Show
import cats.Show
scala> Show[Int].show(42)
val res0: String = 42
Run Code Online (Sandbox Code Playgroud)
发生了什么变化以及从现在开始我们应该如何使用导入?
我正在尝试使用 SignalRef 中断 fs2 流。我使用以下命令设置并运行流。流应在switch包含时运行,并在包含false时中断switchtrue
import cats.effect.IO
import fs2.Stream
import fs2.concurrent.SignallingRef
import scala.concurrent.ExecutionContext
import scala.concurrent.duration.DurationInt
implicit val contextShift = IO.contextShift(ExecutionContext.global)
implicit val timer = IO.timer(ExecutionContext.global)
val switch: IO[SignallingRef[IO, Boolean]] = SignallingRef[IO, Boolean](false)
val program: Stream[IO, Unit] = {
val program: Stream[IO, Unit] =
Stream
.repeatEval(IO{
println(java.time.LocalTime.now)
println(switch.map(_.get).unsafeRunSync.unsafeRunSync)
})
.metered(1.second)
program
.interruptWhen(Stream.repeatEval(switch.map(_.get).unsafeRunSync))
}
program.compile.drain.unsafeRunAsync(() => _)
Run Code Online (Sandbox Code Playgroud)
然后我尝试中断流
switch.map(_.set(true).unsafeRunSync)
Run Code Online (Sandbox Code Playgroud)
然而,这股潮流仍在继续。在标准输出中我看到
15:58:33.048504
false
15:58:34.048760
false
15:58:35.049063
false
15:58:36.049356
false
15:58:37.049615
false
Run Code Online (Sandbox Code Playgroud)
那么显然它没有切换到 true 吗?
我有这个代码编译和工作正常
import cats.implicits._
Cartesian[ValidResponse].product(
getName(map).toValidated,
readAge(map).toValidated
).map(User.tupled)
Run Code Online (Sandbox Code Playgroud)
但是我不喜欢导入,cats.implicits._因为那里的课程太多了.我尝试导入与笛卡尔相关的特定事物
import cats.implicits.catsSyntaxCartesian
import cats.implicits.catsSyntaxUCartesian
import cats.implicits.catsSyntaxTuple2Cartesian
Run Code Online (Sandbox Code Playgroud)
但这些都行不通.作为一个新手,我发现隐式导入非常令人困惑,因为它们只有1000个并且名称不是很明显.我唯一的选择是导入整个宇宙import cats.implicits._并停止思考它.
其实我有更广阔的混乱cats.implicits,cats.instances._和cats.syntax._.到目前为止,我只是通过反复试验导入这些.我不确定何时导入什么.