我正在尝试使用猫库,但我很难在导入和创建的东西之间导航.我的问题如下:
sealed trait Checks
case class CheckViolation(id: Long, msg: String) extends Checks
case class ChecksPassed(ids: Seq[Long]) extends Checks
Run Code Online (Sandbox Code Playgroud)
这是我想要使用的数据结构.每个违规都应该作为具有msg的对象保存,传递的检查可以聚合为仅保存id.
object BusinessRuleSetValidation extends App {
type BRValidationResult = Validated[NonEmptyList[CheckViolation], ChecksPassed]
def run(): BRValidationResult = {
implicit val monoidChecksPassed = new Monoid[ChecksPassed] {
override def empty: ChecksPassed = ChecksPassed(Seq())
override def combine(x: ChecksPassed, y: ChecksPassed): ChecksPassed = ChecksPassed(x.ids ++ y.ids)
}
val check1: BRValidationResult = valid(ChecksPassed(2L))
val check2: BRValidationResult = invalidNel(CheckViolation(1, "This check was violated"))
val check3: BRValidationResult = invalidNel(CheckViolation(2, "This is …Run Code Online (Sandbox Code Playgroud) 给定一个功能
def f(i: I) : S => S
Run Code Online (Sandbox Code Playgroud)
我想写一个非常常见的组合器 g
def g(is : Seq[I], init: S) : S
Run Code Online (Sandbox Code Playgroud)
简单的实现仅使用经典scala
def g(is : Seq[I], init: S) : S =
is.foldLeft(init){ case (acc, i) => f(i)(acc) }
Run Code Online (Sandbox Code Playgroud)
我尝试使用,Foldable但我遇到了编译问题.
import cats._
import cats.Monoid
import cats.implicits._
def g(is : Seq[I], init: S) : S =
Foldable[List].foldMap(is.toList)(f _)(init)
Run Code Online (Sandbox Code Playgroud)
错误是
could not find implicit value for parameter B: cats.Monoid[S => S]
Run Code Online (Sandbox Code Playgroud)
我成功了 State
import cats.data.State
import cats.instances.all._
import cats.syntax.traverse._
def g(is : Seq[I], init: …Run Code Online (Sandbox Code Playgroud) 和猫一起玩,我注意到了一些我无法解释的行为:
import cats.implicits._
...
def wrapA[A, F[_]](v: A)(implicit F: Applicative[F]): F[A] = F.pure(v)
Run Code Online (Sandbox Code Playgroud)
不是一个特别有用的方法,只是玩耍.
完全参数化方法或传递所需的实例显然工作正常:
val o: Option[Int] = wrapA[Int, Option](1)
val o: Option[Int] = wrapA(1)(catsStdInstancesForOption)
Run Code Online (Sandbox Code Playgroud)
这不是类型检查:
val o: Option[Int] = wrapA(1) // found scala.util.Try[Int], required Option[Int]
Run Code Online (Sandbox Code Playgroud)
好的,TryInstances在之前解决了OptionInstances
trait AllInstances
...
with OptionInstances
...
with TryInstances
with TupleInstances
...
Run Code Online (Sandbox Code Playgroud)
但那么为什么没有Tuple2预料到Try呢?在TupleInstances解决之前TryInstances并定义Applicative实例.是arity吗?实例的顺序是否有特殊原因?虽然我看到值类型不会影响隐式解析,但为什么不呢?
Cats 0.9.0,Scala 2.12.1
谢谢.
编辑似乎没有任何Applicative实例Tuple2,因此没有pure,所以这部分问题似乎已经解决了.
我正在使用猫,想知道如何使用它来转换数据.
从
val data = Either[Error, Option[Either[Error, Account]]]
Run Code Online (Sandbox Code Playgroud)
至
val target: Either[Error, Option[Account]] = howToConvert(data)
Run Code Online (Sandbox Code Playgroud)
如果有任何Error发生,结果将Left(error)与第一个出现的错误.
我现在可以用:
data match {
case Left(e) => Left(e)
case Right(Some(Right(y))) => Right(Some(y))
case Right(Some(Left(e))) => Left(e)
case Right(None) => Right(None)
}
Run Code Online (Sandbox Code Playgroud)
但我正在寻找一些简单的方法
我目前正在使用EitherT堆叠Futures和Eithers:
type ErrorOr[A] = Either[Error, A]
def getAge: Future[ErrorOr[Int]] = ???
def getDob(age: Int): ErrorOr[LocalDate] = ???
for {
age <- EitherT(getAge)
dob <- EitherT.fromEither[Future](getDob(age))
} yield dob
Run Code Online (Sandbox Code Playgroud)
我现在想介绍一下Writer monad ie
type MyWriter[A] = Writer[Vector[String], ErrorOr[A]]
def getAge: Future[MyWriter[Int]] = ???
def getDob(age: Int): MyWriter[LocalDate] = ???
Run Code Online (Sandbox Code Playgroud)
我的问题是,对调用getAge和getDob调用进行排序的最佳方法是什么?我知道monads可以堆叠,Future -> Writer -> Either但是我可以继续EitherT在这种情况下使用吗?如果是这样的话?
在SO上给出了一个解释,为什么像scalaz,猫(Scala)或Arrow(Kotlin)这样的验证不能成为monad.
据我所知,这是因为他们已经根据应用函子和所需的验证行为对monad进行建模,因为应用程序(收集所有残留物)与作为monad的验证的所需行为不同(序列验证并快速失败)第一个无效).因此,当您希望快速发生故障时,您需要将验证转换为其中一个(这是一个monad).
在https://groups.google.com/forum/#!msg/scalaz/IWuHC0nlVws/syRUkXJklWIJ上,他们提到验证不是monad的原因,是因为以下属性不会成立:
x <|*|> y === x >>= (a => y map ((a, _)))
Run Code Online (Sandbox Code Playgroud)
但是看一个monad的定义,上面的属性不是monad法则的一部分.那么,这是因为monad是以应用程序的形式实现的,还是上述属性是monad的先决条件?
这种更高级的推理对我来说都是新的,但是由于我对FP的理解有限,我可以使用一种验证数据类型,当用作应用程序(累积invalids)时有一种行为,当用作monad时有另一种行为(快速失败).
首先,对不起,但我不是英语为母语的人。但是,我会尽力而为。
我实际上是在学习一些理论概念,以此作为加深对函数式编程的理解的兴趣,并提出一些问题来检查我是否正确理解了类人动物。
首先,我发现的一个monoid的定义是,一个monoid是一个在关联二进制运算下关闭且具有标识元素的集合。我想是对的吗?
因此,使用以下定义,我假设Scala的列表在:::运算符下形成一个Monoid (作为List一个集合),:::是关联的(xs ::: (ys ::: zs) = (xs ::: ys) ::: zs)并且List具有基本元素(Nil)。我对吗?
关于monoid,关于:: List操作员有什么要说的吗?我想不是因为它不是以两个列表作为参数,而是一个元素和一个List。我还对吗?
我有一个类,该类具有一个参数方法,该方法可产生结果并返回与自身类似的对象,但具有更新的状态供以后使用。
例如,下面包含此类的简单示例以及如何使用它:
case class Foo(x: Double) {
def bar(y: Double): (Foo, Double) = (Foo(x + y), x / (x + y))
}
val res = Vector(1.0,2.0,3.0,4.0).foldLeft((Foo(0), 0.0))((foo, x) => foo._1.bar(x))
res._1.bar(3.0)
Run Code Online (Sandbox Code Playgroud)
我已经看过Cats State monad,并希望我可以使用它避免使状态(“ x”成员)混乱。这里的示例接近我想要的示例,但是返回新状态的函数没有任何参数,并且状态不会在类似循环的操作中传递(而是在表达式之间传递)。关于Cats,我是一个完全的新手,但是我是否吠错了树?
我有以下代码:
import cats.effect.IO
import cats.data.State
import cats.data.StateT
import cats.implicits._
import cats.effect.LiftIO
abstract class Example {
object implicits {
implicit def myEffectLiftIO: LiftIO[IOGameplay] =
new LiftIO[IOGameplay] {
override def liftIO[A](ioa: IO[A]): IOGameplay[A] = {
StateT.liftF(ioa)
}
}
}
type Gameplay[A] = State[GameState, A]
type IOGameplay[A] = StateT[IO, GameState, A]
type EitherDirection[A] = Either[Throwable, A]
type Map = Array[Array[FieldType]]
sealed trait FieldType
case class GameState(map: Map, block: Block)
case class Block(f1: Field, f2: Field)
case class Field()
import implicits._
val L = …Run Code Online (Sandbox Code Playgroud) scala-cats ×10
scala ×8
arrow-kt ×2
monads ×2
scalaz ×2
applicative ×1
cats-effect ×1
either ×1
f# ×1
implicit ×1
monoids ×1
option ×1
traits ×1