我有以下情况,给出两种类型,MA并且MB,我希望能够证明它们不仅具有一个,Applicative而且它们都具有相同的底层形状.我尝试过以下操作:
type UnapplyM[TC[_[_]], MA, M0[_]] = Unapply[TC, MA]{ type M[X] = M0[X] }
implicit def thing[MA, MB, M[_]](implicit un: UnapplyM[Applicative,MA,M], un2: UnapplyM[Applicative,MB,M]) = ...
Run Code Online (Sandbox Code Playgroud)
但是继续遇到不同的含义(即这不起作用.)A类型参数Unapply和工作类型投影可以做类似的事情.
这有一种方法可以采用这两种类型并且能够证明它们实际上是由同一类型类实例支持的吗?
我有一个实例,Either[Future[A], Future[B]]我想将其转换为Future[Either[A, B]].
自从我上一个问题以来,已经发布了cat 0.8.1,改变了库的结构并Xor倾向于支持Either,这在2.12中是正确的.
因此,先前接受的答案中描述的方法不再起作用.我试图找到合适的进口但失败了.
cats.instances.either._
cats.implicits._
cats.syntax.bitraverse._
Run Code Online (Sandbox Code Playgroud)
看起来似乎有道理,但不幸的是不起作用.编译仍然失败value bisequence is not a member of Either[scala.concurrent.Future[A],scala.concurrent.Future[??B]]
扩展导入*.all._并没有改变编译器错误.
我在scala 2.11.8上,因为项目所依赖的所有库都没有发布2.12版本
如何M在下面的方法中使用for-comprehension类型?
def foo[M[_]: Monad](m1: M[Int], m2: M[Int]) =
for {
a <- m1
b <- m2
} yield (a + b)
Run Code Online (Sandbox Code Playgroud)
我会得到一个
value flatMap is not a member of type parameter M[Int]
Run Code Online (Sandbox Code Playgroud)
我可以通过定义flatMap和map方法来使它工作:
implicit class MOps[A](m: M[A])(implicit monad: Monad[M]) {
def flatMap[B](f: A => M[B]): M[B] = monad.flatMap(m)(f)
def map[B](f: A => B): M[B] = monad.map(m)(f)
}
Run Code Online (Sandbox Code Playgroud)
但是肯定有必要让Cats提供这些方法吗?
我想组合多个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) 标准库提供以下unzip方法List:
scala>val l = List((1, "one"), (2, "two"), (3, "three"), (4, "four"), (5, "five"))
scala> l.unzip
// res13: (List[Int], List[String]) = (
// List(1, 2, 3, 4, 5),
// List("one", "two", "three", "four", "five")
//)
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以NonEmptyList从cats库中实现相同目的:
scala> import cats.data.NonEmptyList
scala> val nel = NonEmptyList.of((1, "one"), (2, "two"), (3, "three"), (4, "four"), (5, "five"))
//res15: NonEmptyList[(Int, String)] = NonEmptyList(
// (1, "one"),
// List((2, "two"), (3, "three"), (4, "four"), (5, "five"))
//)
Run Code Online (Sandbox Code Playgroud) 说我有三个数据库访问功能foo,bar以及baz可在每个返回Option[A],其中A一些模型类,并调用互相依赖.
我想按顺序调用函数,并且在每种情况下,如果找不到值,则返回相应的错误消息(None).
我当前的代码如下所示:
Input is a URL: /x/:xID/y/:yID/z/:zID
foo(xID) match {
case None => Left(s"$xID is not a valid id")
case Some(x) =>
bar(yID) match {
case None => Left(s"$yID is not a valid id")
case Some(y) =>
baz(zID) match {
case None => Left(s"$zID is not a valid id")
case Some(z) => Right(process(x, y, z))
}
}
}
Run Code Online (Sandbox Code Playgroud)
可以看出,代码严重嵌套.
相反,我使用for理解,我不能给出具体的错误信息,因为我不知道哪一步失败了:
(for {
x <- foo(xID) …Run Code Online (Sandbox Code Playgroud) 以下是使用IO Monad的一些Scala猫代码:
import java.util.concurrent.{ExecutorService, Executors}
import cats.effect.IO
import scala.concurrent.{ExecutionContext, ExecutionContextExecutor}
import scala.util.control.NonFatal
object Program extends App {
type CallbackType = (Either[Throwable, Unit]) => Unit
// IO.async[Unit] is like a Future that returns Unit on completion.
// Unlike a regular Future, it doesn't start to run until unsafeRunSync is called.
def forkAsync(toRun: () => Unit)(executor: ExecutorService): IO[Unit] = IO.async[Unit] { callback: CallbackType =>
// "callback" is a function that either takes a throwable (Left) or whatever toRun returns (Right). …Run Code Online (Sandbox Code Playgroud) 我正在使用Scala Cats库中的State monad来以功能方式构成命令转换的命令式序列。
我的实际用例非常复杂,因此,为简化起见,请考虑以下最小问题:存在一种Counter状态,其计数值可能会递增或递减;但是,如果计数变为负数或溢出,则表示错误。万一遇到错误,我需要在发生错误时保留状态,并有效地停止处理后续的状态转换。
我使用type,使用每个状态转换的返回值报告任何错误Try[Unit]。成功完成的操作将返回新状态加该值Success(()),而失败将返回现有状态以及包装在其中的异常Failure。
注意:显然,遇到错误时,我可以抛出异常。但是,这将违反引用透明性,并且还需要我做一些额外的工作才能将计数器状态存储在抛出的异常中。我也打折了使用a Try[Counter]作为状态类型(而不是just Counter),因为我不能使用它来跟踪失败和失败状态。我尚未探讨的一种选择是使用(Counter, Try[Unit])元组作为状态,因为这似乎太麻烦了,但是我愿意提出建议。
import cats.data.State
import scala.util.{Failure, Success, Try}
// State being maintained: an immutable counter.
final case class Counter(count: Int)
// Type for state transition operations.
type Transition[M] = State[Counter, Try[M]]
// Operation to increment a counter.
val increment: Transition[Unit] = State {c =>
// If the count is at its maximum, incrementing it …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)
我想所有这些都是纯粹的和确定性的。只是不是参照透明的,因为每次生成的实例都是不同的。那是使用效果类型的好时机吗?还是这里会有不同的功能模式?
scala ×10
scala-cats ×10
cats-effect ×3
applicative ×1
either ×1
io-monad ×1
monads ×1
nested ×1
option ×1
scalaz ×1
state-monad ×1