我正在尝试为Monad具有多个类型参数的类型实现cat 实例.我看着猫的Either实例,看看它是如何在那里完成的.Either Monad来自猫的部分实例代码复制如下:
import cats.Monad
object EitherMonad {
implicit def instance[A]: Monad[Either[A, ?]] =
new Monad[Either[A, ?]] {
def pure[B](b: B): Either[A, B] = Right(b)
def flatMap[B, C](fa: Either[A, B])(f: B => Either[A, C]): Either[A, C] =
fa.right.flatMap(f)
}
}
Run Code Online (Sandbox Code Playgroud)
它无法编译错误: error: not found: type ?
什么是?类型,如何在为自己的类型创建实例时使用它?
通过使用Scala和Cats(或者可能是另一个专注于类别理论和/或函数式编程的库),以最具功能性(代数)的方式解决这个问题的最佳方法是什么?
如果我们有以下方法执行REST API调用来检索单个信息?
type FutureApiCallResult[A] = Future[Either[String, Option[A]]]
def getNameApiCall(id: Int): FutureApiCallResult[String]
def getAgeApiCall(id: Int): FutureApiCallResult[Int]
def getEmailApiCall(id: Int): FutureApiCallResult[String]
Run Code Online (Sandbox Code Playgroud)
如您所见,它们会产生异步结果.Either monad用于在API调用期间返回可能的错误,而Option用于在API未找到资源时返回None(这种情况不是错误,而是可能的和期望的结果类型).
case class Person(name: String, age: Int, email: String)
def getPerson(id: Int): Future[Option[Person]] = ???
Run Code Online (Sandbox Code Playgroud)
如果任何API调用失败或任何API调用返回None(整个Person实体无法组合),则此方法应使用上面定义的三个API调用方法异步组合并返回Person或None.
出于性能原因,所有API调用必须以并行方式完成
我认为最好的选择是使用Cats Semigroupal Validated但是在尝试处理Future和如此多的嵌套Monads时我迷路了:S
任何人都可以告诉我你将如何实现这一点(即使改变方法签名或主要概念)或指向我正确的资源?我在编码时对Cats和Algebra很新,但我想学习如何处理这种情况,以便我可以在工作中使用它.
鉴于:
def convert[T](list: List[Either[String, T]]): Validated[NonEmptyList[String], NonEmptyList[T]] =
NonEmptyList.fromList(list)
.toRight("list is empty")
.flatMap(...
Run Code Online (Sandbox Code Playgroud)
我如何平面图NonEmptyList[Either[String, T]]最终我最终得到了我的Validated回报值?
cats库中有什么可以解释这种情况吗?或者我是否需要手动执行以下操作:将Eithers列表转换为列表之一的最佳方法?
我创建了一个列表,IO[Unit]以便从URL列表中检索数据.但现在我如何将它转换回单一IO[Unit]?
我想转换List[Either[String, Int]]en 的列表Either[String, List[Int]].为此,我想使用Cats.sequence:
/* for ammonite users
interp.load.ivy("org.typelevel" %% "cats-core" % "1.0.1")
@
*/
import cats.instances.list._
import cats.instances.either._
import cats.syntax.traverse._
val seqCorrect: List[Either[String, Int]] = List(Right(1), Right(2), Right(3))
val result1 = seqCorrect.sequence
Run Code Online (Sandbox Code Playgroud)
但是我有以下错误:
Cannot prove that Either[String,Int] <:< G[A].
val result1 = seqCorrect.sequence
^
Run Code Online (Sandbox Code Playgroud)
我发现错误消息非常无益.我该如何解决这个问题?
我有下一个使用Cats IO编写的代码,它并行执行多个动作(简化):
import cats.effect._
import cats.implicits._
import scala.concurrent.ExecutionContext.Implicits.global
class ParallelExecIO {
def exec: IO[List[String]] = {
val foo = IO.shift *> IO("foo")
val bar = IO.shift *> IO("bar")
List(foo, bar).parSequence
}
}
Run Code Online (Sandbox Code Playgroud)
是否可以使用效果抽象重写此代码?应提供哪些类型的证据?
样品:
class ParallelExecIO[F[_]: ConcurrentEffect /* ??? */] {
def exec: F[List[String]] = {
val foo = Async.shift[F](implicitly) *> "foo".pure[F]
val bar = Async.shift[F](implicitly) *> "bar".pure[F]
List(foo, bar).parSequence
}
}
Run Code Online (Sandbox Code Playgroud)
[error] value parSequence不是List [F [String]]的成员
是否可以使用Doobie并行运行多个查询?
我有以下(伪)查询:
def prepareForQuery(input: String): ConnectionIO[Unit] = ???
val gettAllResults: ConnectionIO[List[(String, BigDecimal)]] = ???
def program(input : String) : ConnectionIO[List[(String, BigDecimal)]] = for{
_ <- prepareForQuery(input)
r <- gettAllResults
} yield r
Run Code Online (Sandbox Code Playgroud)
我尝试了以下内容:
import doobie._
import doobie.implicits._
import cats.implicits._
val xa = Transactor.fromDataSource[IO](myDataSource)
val result = (program(i1),program(i2)).parMapN{case (a,b) => a ++ b}
val rs = result.transact(xa).unsafeRunSync
Run Code Online (Sandbox Code Playgroud)
但是,找不到的NonEmptyParallel实例ConnectionIO。
错误:(107,54)找不到参数p的隐式值:cats.NonEmptyParallel [doobie.ConnectionIO,F] val结果=(program(i1),program(i2))。parMapN {case(a,b)= > a ++ b}
我是否缺少明显的东西或尝试无法完成的事情?谢谢
我试图理解Lenses scalaz(令人惊讶的是没有发现类似的东西cats-core)我遇到了所谓Store的类型别名:
type StoreT[F[_], A, B] = IndexedStoreT[F, A, A, B]
type IndexedStore[I, A, B] = IndexedStoreT[Id, I, A, B]
type Store[A, B] = StoreT[Id, A, B]
Run Code Online (Sandbox Code Playgroud)
哪里
final case class IndexedStoreT[F[_], +I, A, B](run: (F[A => B], I))
Run Code Online (Sandbox Code Playgroud)
问题是如何对待这种类型?文档只是引用了Lenses.用几句话就可以解释一下吗?
对我来说,它看起来类似于Statemonad,其中"状态转换"存储功能F[A => B]
我正在尝试使用cats-effect以纯粹的功能方式获取一些基本文件IO(写入/读取)。遵循本教程之后,下面就是我读取文件的内容:
private def readFile(): IO[String] = for {
lines <- bufferedReader(new File(filePath)).use(readAllLines)
} yield lines.mkString
def bufferedReader(f: File): Resource[IO, BufferedReader] =
Resource.make {
IO(new BufferedReader(new FileReader(f)))
} { fileReader =>
IO(fileReader.close()).handleErrorWith(_ => IO.unit)
}
Run Code Online (Sandbox Code Playgroud)
现在在handleErrorWith函数中,我可以记录发生的任何错误,但是如何为它添加适当的错误处理(例如,返回Resource[IO, Either[CouldNotReadFileError, BufferedReader]])?
我正在尝试在doobie存储库的代码中隐式添加Async和Sync。Sync和Async [F]可以正常工作IO。我想将它们转换为未来并面临问题
我试图从IO创建自己的Aync
def futureAsync(implicit F: MonadError[Future, Throwable]): Async[Future] = new Async[Future] {
override def async[A](k: (Either[Throwable, A] => Unit) => Unit): Future[A] = IO.async(k).unsafeToFuture()
override def asyncF[A](k: (Either[Throwable, A] => Unit) => Future[Unit]): Future[A] =
throw new Exception("Not implemented Future.asyncF")
override def suspend[A](thunk: => Future[A]): Future[A] = thunk
override def bracketCase[A, B](acquire: Future[A])(use: A => Future[B])(release: (A, ExitCase[Throwable]) => Future[Unit]): Future[B] =
throw new Exception("Not implemented Future.bracketCase")
override def raiseError[A](e: Throwable): Future[A] = F.raiseError(e)
override def handleErrorWith[A](fa: Future[A])(f: Throwable …Run Code Online (Sandbox Code Playgroud)