Scala 使用Int=>;筛选F[List[Int]];F[Boolean],其中F为泛型

Scala 使用Int=>;筛选F[List[Int]];F[Boolean],其中F为泛型,scala,generic-programming,scala-cats,Scala,Generic Programming,Scala Cats,我试图定义一个抽象代数,它允许我推迟选择将用于包装有效操作(IO、任务、未来等)的Monad,直到我运行程序 trait MyAlg[F[_]] def isValid(v: int): F[Boolean] def getElements(): F[List[Int]] def filterValidElements(vs: F[List[Int]]): F[List[Int]] 假设我需要在isValid中执行一些可能会产生副作用的操作,比如检查数据库 如果我可以将isVali

我试图定义一个抽象代数,它允许我推迟选择将用于包装有效操作(IO、任务、未来等)的Monad,直到我运行程序

trait MyAlg[F[_]]
  def isValid(v: int): F[Boolean]
  def getElements(): F[List[Int]]
  def filterValidElements(vs: F[List[Int]]): F[List[Int]]
假设我需要在
isValid
中执行一些可能会产生副作用的操作,比如检查数据库

如果我可以将
isValid
getElements
抽象保留下来,例如,一个实现可以连接到数据库,另一个实现可以引用mock进行测试,但是定义一个通用的
filterValidElements
,这样我就不需要为这两种情况重新实现相同的函数。大概是这样的:

def filterValidElements(es: F[List[Int]]]): F[List[Int]] = 
      es.map(
        elems => elems.map(
          e => (e, isValid(e))).collect{
            case (e, F(true)) => e
       })
但是,
F
是泛型的,因此它不提供
map
,也没有构造函数

当然,我不能明确地将
F
设置为单子,例如

trait MyAlg[F: cats.Monad]
因为traits不能具有具有上下文边界的类型参数

有没有办法编写我的
filterValidElements
函数,让
isValid
abstract和
F
generic


我对这种风格很陌生,所以我可能完全走错了方向

尝试添加隐式参数,指定您可以执行
映射
(即
函子
)和
aka
(即
不变单体
)。例如,您可以使其
应用
Monad

import cats.{Functor, InvariantMonoidal}
import cats.syntax.functor._
import scala.language.higherKinds

trait MyAlg[F[_]] {
  def isValid(v: Int): F[Boolean]
  def getElements(): F[List[Int]]
  def filterValidElements(es: F[List[Int]])(implicit functor: Functor[F], im: InvariantMonoidal[F]): F[List[Int]] =
    es.map(
      elems => elems.map(
        e => (e, isValid(e))).collect{
          case (e, fb) if fb == im.point(true) => e
        })
}

这是非常接近工作。我必须将es.map更改为函子[F].map(es),然后它才能工作。谢谢。也许你没有导入cats.syntax.functor.\uu。如果您这样做了,您应该能够编写
es.map(..)
。一定要导入。