当您的计算步骤是独立的时,通常会提到应用仿函数作为monad的替代.他们经常提到的一个优点是,当你想要堆叠应用程序时,你不需要变换器,因为F[G[X]]它总是一个应用程序.假设我有以下功能:
def getDataOption(): Option[Data]
def getUserFuture(): Future[User]
def process(data: Data, user: User)
Run Code Online (Sandbox Code Playgroud)
我想有优雅的堆叠,以获得Future[Option[User]]与Future[Option[Data]]和地图与process.
到目前为止,我只想出了这个(使用Cats):
Applicative[Future]
.compose[Option]
.map2(
Applicative[Future].pure(getDataOption()),
getUserFuture().map(Applicative[Option].pure))(process)
Run Code Online (Sandbox Code Playgroud)
但我相信这远非理想.是否有更优雅和通用的方式来实现相同的目标?
我正在学习Scala中的Free monad,我已经汇总了一个代数的简单例子,我可以使用猫将其升级为Free monad.
这是我的代数
sealed trait ConsultationOp[A]
object consultation {
case class Create(c: Consultation) extends ConsultationOp[Unit]
case class Get(s: ConsultationId) extends ConsultationOp[Option[Consultation]]
}
Run Code Online (Sandbox Code Playgroud)
我可以像使用它一样
def app = for {
c <- consultation.Create(Consultation("123", "A consultation"))
_ <- consultation.Get(c._id)
} yield ()
def interpreters = ConsultationInterpreter or UserInterpreter
app.foldMap(interpreters)
Run Code Online (Sandbox Code Playgroud)
当从提升ConsultationOp到Free隐式执行.
(缺少很多细节,完整的工作实现在这里:https://github.com/gabro/free-api)
到目前为止一切都那么好,但是如果我需要提取返回的可选值呢consultation.Get?
首先想到的是monad变换器,即类似的东西
def app = for {
c <- consultation.Create(Consultation("123", "A consultation")).liftM[OptionT]
d <- OptionT(consultation.Get(c._id))
_ <- doSomethingAConsultation(d)
} yield () …Run Code Online (Sandbox Code Playgroud) 我试图OptionT结合Future[Option[T]]在for-comprehension中返回的方法.
import cats.data._
import cats.implicits._
import cats.instances.future._
for {
data <- OptionT(repo.getData(id))
...
}
Run Code Online (Sandbox Code Playgroud)
我得到的编译器错误:
could not find implicit value for parameter F cats.Functor[scala.concurrent.Future]
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么?
谢谢
假设我想从2个远程服务聚合数据,并尽可能快地提供响应:
def loadUser: Future[User]
def loadData: Future[Data]
case class Payload(user: User, data: Data)
Run Code Online (Sandbox Code Playgroud)
我知道这个顺序执行异步任务:
for {
user <- loadUser
data <- loadData
} yield Payload(user,data)
Run Code Online (Sandbox Code Playgroud)
虽然这个并行执行它们,因为异步任务在顺序链接之前被触发:
val userF = loadUser
val dataF = loadData
for {
user <- userF
data <- dataF
} yield Payload(user,data)
Run Code Online (Sandbox Code Playgroud)
然而,差异对我来说有点过于含蓄,有些人可能最初没有注意到它.
申请人也解决了这个问题
(loadUser |@| loadData) { Payload(_,_) }
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我在应用程序和monad之间使用什么来执行并行异步计算吗?每种方法的优缺点是什么?
我正在使用猫Scala库,IntelliJ IDE似乎正在努力使用implicits:
这是一个简单的例子:
import cats.std.all._
import cats.Traverse.ops._
def useSequence[A](ls : List[Option[A]]) : Option[List[A]] = {
ls.sequence
}
Run Code Online (Sandbox Code Playgroud)
在IntelliJ中,此代码以红色突出显示.但是我可以使用Make Project或命令行构建得很好.
现在错误是:
类型Nothing [List [Nothing]]的表达式不符合预期类型选项[List [A]]
其他时候错误是这样的:
值序列不是List [Option [A]]的成员
这是IntelliJ中的错误还是我错过了一些配置?
我使用的是IntelliJ 15.0.2和Scala插件的2.0.4版.
在函数流的 Scala fs2 库中:
我想明白之间的差别flatMap,flatTap,evalMap和evalTap。它们似乎都执行相同的操作,即流值的转换。
有什么区别以及何时应该使用它们中的每一个?
Scala社区.
目前我正在尝试使用猫ValidatedMonad 实现自定义模型/单参数验证.但是,从1.0开始删除笛卡尔积之后,我无法使用(v1 | @ | v2)map(f)并且无法编译我的代码:
import cats.Semigroupal
import cats.data.Validated.{Invalid, Valid}
import cats.data.{ValidatedNel, _}
import cats.implicits._
import cats.instances.all._
case class FieldErrorInfo(name: String, error: String)
type FieldName = String
type ValidationResult[A] = ValidatedNel[FieldErrorInfo, A]
trait SingleFieldValidationRule[U] extends ((U, FieldName) => ValidationResult[U])
trait ModelValidationRule[M] extends (M => ValidationResult[M])
object ValidateNameRule extends SingleFieldValidationRule[String] {
override def apply(v1: String, name: String): ValidationResult[String] = {
if (v1.contains("cats"))
v1.validNel
else
FieldErrorInfo(name, "Some Error").invalidNel
}
}
object ValidateQuantityRule extends SingleFieldValidationRule[Int] {
override def apply(v1: …Run Code Online (Sandbox Code Playgroud) 我需要将一系列cats.data.ValidatedNel[E, T]值展平为单个ValidatedNel值:
val results: Seq[cats.data.ValidatedNel[E, T]] = ???
val flattenedResult: cats.data.ValidatedNel[E, T]
Run Code Online (Sandbox Code Playgroud)
我可以这样做:
import cats.std.list._, cats.syntax.cartesian._
results.reduce(_ |@| _ map { case _ => validatedValue })
Run Code Online (Sandbox Code Playgroud)
但是想知道是否存在预定义的库方法.
在2013 年的这个问题中,奥德斯基先生指出,"现在判断"像Scalaz这样的图书馆是否能够在Dotty下存在(至少在他们当前的状态下),这是由于高级和存在类型的阉割所致.
在过去的时间里,Dotty对Scalaz&Cats的影响已被阐明了吗?内置效果和记录等提议的功能是否会改变这些项目的范围?
我知道Dotty仍然可以替代scalac,但是当我考虑投入时间将纯粹的功能结构和方法应用到我的工作中时,我认为考虑其旗舰库的未来很重要.
scala ×10
scala-cats ×10
scalaz ×4
monads ×2
applicative ×1
dotty ×1
free-monad ×1
fs2 ×1
future ×1
implicits ×1
scala-2.12 ×1