标签: scala-cats

带有 Coproduct 和 monad 转换器的 Scala Free Monads

我正在尝试在我的项目中开始使用免费的 monad,我正在努力让它变得优雅。
假设我有两个上下文(实际上我有更多) -Receipt而且User- 都对数据库进行了操作,我希望将它们的解释器分开并在最后一刻组合它们。
为此,我需要为每个操作定义不同的操作,并使用Coproduct.
这是我经过几天的谷歌搜索和阅读后的结果:

  // Receipts
sealed trait ReceiptOp[A]
case class GetReceipt(id: String) extends ReceiptOp[Either[Error, ReceiptEntity]]

class ReceiptOps[F[_]](implicit I: Inject[ReceiptOp, F]) {
  def getReceipt(id: String): Free[F, Either[Error, ReceiptEntity]] = Free.inject[ReceiptOp, F](GetReceipt(id))
}

object ReceiptOps {
  implicit def receiptOps[F[_]](implicit I: Inject[ReceiptOp, F]): ReceiptOps[F] = new ReceiptOps[F]
}

// Users
sealed trait UserOp[A]
case class GetUser(id: String) extends UserOp[Either[Error, User]]

class UserOps[F[_]](implicit I: Inject[UserOp, F]) {
  def getUser(id: String): Free[F, Either[Error, User]] = …
Run Code Online (Sandbox Code Playgroud)

scala monad-transformers free-monad scala-cats

5
推荐指数
1
解决办法
486
查看次数

猫效应和 IO 单子

我已经尝试掌握 IO monad 一段时间了,这是有道理的。如果我没记错的话,目标是将副作用的描述和实际执行分开。如下例所示,Scala 有一种方法可以获取非引用透明的环境变量。出现了两个问题。

问题一:这个是参照透明的吗

问题 2:如何正确(基于单位/属性)测试这一点?不可能检查相等性,因为它将检查内存引用,并且不可能检查内部函数,因为如果我没有弄错的话,函数比较是不可能的。但是,我不想在单元测试中运行实际的副作用。另外,这是设计错误还是 IO monad 的误用?

case class EnvironmentVariableNotFoundException(message: String) extends Exception(message)

object Env {
  def get(envKey: String): IO[Try[String]] = IO.unit.flatMap((_) => IO.pure(tryGetEnv(envKey)))

  private[this] def tryGetEnv(envKey: String): Try[String] =
    Try(System.getenv(envKey))
      .flatMap(
        (x) =>
          if (x == null) Failure(EnvironmentVariableNotFoundException(s"$envKey environment variable does not exist"))
          else Success(x)
      )
}
Run Code Online (Sandbox Code Playgroud)

monads functional-programming scala scala-cats

5
推荐指数
1
解决办法
1882
查看次数

列表Kleisli to Kleisli列表

我想知道是否有办法把List[Kleisli[Option, Int, Int]]Kleisli[Option, Int, List[Int]].

特别是我有像这样形成的kleisli列表:

def k(a: String) = Kleisli[Option, Int, Int](m => Some(a.length * m))
val kList = List("hi", "hello").map(k)
Run Code Online (Sandbox Code Playgroud)

我所做的是以下内容

Kleisli[Option, Int, List[Int]](m => kList.map(_.run(m)).sequence)
Run Code Online (Sandbox Code Playgroud)

这是非常混乱,没有表现力,需要大量的手工工作.

有没有更好的办法?

scala kleisli scala-cats

5
推荐指数
1
解决办法
219
查看次数

Scala 和 cats:到 Identity monad 的隐式转换

我有一个计算数字类型的平方和的函数,如下所示。

import cats.syntax.functor._
import cats.syntax.applicative._
import cats.{Id, Monad}

import scala.language.higherKinds

object PowerOfMonads {
       /**
        * Ultimate sum of squares method
        *
        * @param x First value in context
        * @param y Second value in context
        * @tparam F Monadic context
        * @tparam T Type parameter in the Monad
        * @return Sum of squares of first and second values in the Monadic context
        */
    def sumOfSquares[F[_]: Monad, A, T >: A](x: F[A], y: F[A])(implicit num: Numeric[T]) : F[T] = {
        def …
Run Code Online (Sandbox Code Playgroud)

monads scala implicit implicit-conversion scala-cats

5
推荐指数
1
解决办法
1784
查看次数

Scala 是否支持类型构造函数的部分应用?

我正在从scala-exercises学习 Cats 。
想知道如何使用高阶类型,有一些尝试:

 trait Functor[F[_]] {
   def map[A, B](fa: F[A])(f: A => B): F[B]
 }

 def someThingFail1[In]() = new Functor[Function1[In, _]] {
    override def map[A, B](fa: Function1[In, A])(f: A => B): Function1[In, B] = ???
  }

  def someThingFail2[In]() = new Functor[Either[In, _]] {
    override def map[A, B](fa: Either[In, A])(f: A => B): Either[In, B] = ???
  }

  def someThingFail3() = new Functor[List[_]] {
    override def map[A, B](fa: List[A])(f: A => B): List[B] = ???
  }

  //only this …
Run Code Online (Sandbox Code Playgroud)

scala type-constructor scala-cats

5
推荐指数
1
解决办法
408
查看次数

无法找到参数半群的隐式值

我只是尝试编译以下代码:

import cats.Monoid
import cats.instances.boolean._ // for Monoid
import cats.instances.int._ // for Monoid
import cats.instances.list._ // for Monoid
import cats.instances.string._ // for Monoid
import cats.syntax.apply._ // for imapN
import cats.syntax.semigroup._

case class Cat2(name: String, yearOfBirth: Int, favoriteFoods: List[String])

object FancyFunctor {

  val tupleToCat: (String, Int, List[String]) => Cat2 =
    Cat2.apply _

  val catToTuple: Cat2 => (String, Int, List[String]) =
    cat => (cat.name, cat.yearOfBirth, cat.favoriteFoods)

  implicit val catMonoid: Monoid[Cat2] = (
    Monoid[String],
    Monoid[Int],
    Monoid[List[String]]
  ).imapN(tupleToCat)(catToTuple)

  def main(args: Array[String]): Unit = { …
Run Code Online (Sandbox Code Playgroud)

scala scala-cats

5
推荐指数
1
解决办法
1861
查看次数

Scala、Cats、Intellij IDEA:修复语法和编译错误?

即使终端 SBT 工作正常,在 IntelliJ IDEA 中使用 Scala 的 Cats 库也会导致错误。我们能解决这个问题吗?或者一些不切换编辑器的解决方法?

scala intellij-idea scala-cats

5
推荐指数
1
解决办法
486
查看次数

模拟 BlazeClientBuilder[IO] 以返回模拟客户端[IO]

我正在使用该BlazeClientBuilder[IO].resource方法来获取Client[IO]. 现在,我想模拟客户端进行单元测试,但不知道该怎么做。有没有一个好的方法来嘲笑这个,我会怎么做?

class ExternalCall(val resource: Resource[IO, Client[IO]], externalServiceUrl: Uri) {
def retrieveData: IO[Either[Throwable, String]] = {
for {
  req <- IO(Request[IO](Method.GET, uri = externalServiceUrl))
  response <- resource.use(client => {
    client.fetch[String](req)(httpResponse => {
      if (!httpResponse.status.isSuccess)
        throw new Exception(httpResponse.status.reason)
      else
        httpResponse.as[String]
    })
  })
} yield Right(response)
}
}
Run Code Online (Sandbox Code Playgroud)

来电代码

new ExternalCall(BlazeClientBuilder[IO](global).resource).retrieveData
Run Code Online (Sandbox Code Playgroud)

scala mockito io-monad scala-cats

5
推荐指数
1
解决办法
1723
查看次数

ConcurrentHashMap 与函数式编程。暂停 unsafeRun 安全吗?

unsafeRunSync问题:使用暂停是否安全IO?例如

val io: IO[Unit] = //...
val io2: IO[Unit] = IO(io.unsafeRunSync)
Run Code Online (Sandbox Code Playgroud)

我这样做的原因是我有一些参数化的类,F[_]: Effect它就像一个缓存:

import cats.effect.Effect

final class MyChache[F[_]](implicit F: Effect[F]) {
  private val cache = new ConcurrentHashMap[Int, String]

  def getOrCreate(key: Int): F[String] = F delay {
    cache.computeIfAbsent(
      key, 
      k => longRunningEffecfulComputation(k).toIO.unsafeRunSync() // <-- Here
    )
  }
}


object MyCache {
  def longRunningEffecfulComputation[F[_] : Effect](key: Int): F[String] = {
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

重点是我只想为每个键运行一次长时间运行的有效计算(这是相当罕见的)。然而,我希望在检索现有密钥时保持非阻塞。

ConcurrentHashMap似乎是一个完美的选择,但它需要这种带有运行和暂停效果的丑陋技巧。还有更好的方法吗?

concurrency functional-programming scala scala-cats

5
推荐指数
1
解决办法
637
查看次数

猫:映射具有相同应用的元组

假设我有:

val x1: Either[String, Int] = Right(1)
val x2: Either[String, Float] = Left("Nope")
val x3: Either[String, Double] = Left("Not Today")
Run Code Online (Sandbox Code Playgroud)

我想将它们组合在一起并得到一个Either[NonEmptyList[String], (Int, Float, Double)]. 为此,我目前正在执行以下操作:

import cats.syntax.all._
(
  x1.toValidatedNel,
  x2.toValidatedNel,
  x3.toValidatedNel
).tupled
 .toEither
Run Code Online (Sandbox Code Playgroud)

这可以完成工作,但有点乏味。有没有办法toValidatedNel只调用一次来做到这一点?就像是:

(x1, x2, x3)
  .fooMap(_.toValidatedNel)
  .tupled
  .toEither
Run Code Online (Sandbox Code Playgroud)

fooMap猫身上是否存在这样的东西?或者我们需要HLists那个吗?

scala tuples either applicative scala-cats

5
推荐指数
1
解决办法
2274
查看次数