代码之家  ›  专栏  ›  技术社区  ›  Metropolis

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

  •  1
  • Metropolis  · 技术社区  · 6 年前

    我试图定义一个抽象代数,它允许我在运行程序之前推迟选择将用于包装有效操作(IO、Task、Future等)的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 ,比如检查数据库。

    如果我能离开就好了 getElements 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

    当然,我不能明确地设定 作为一个单子,例如

    trait MyAlg[F: cats.Monad]
    

    因为traits不能具有具有上下文边界的类型参数。

    有没有办法写我的信 功能,离开 抽象和 普通的?

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

    1 回复  |  直到 6 年前
        1
  •  2
  •   Dmytro Mitin    6 年前

    map Functor )以及 pure 又称作 point InvariantMonoidal ). 例如,你可以做到 Applicative 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
            })
    }