代码之家  ›  专栏  ›  技术社区  ›  St.Antario

Scala FlatMap和应用程序上下文边界产生编译错误

  •  0
  • St.Antario  · 技术社区  · 6 年前

    我在Scala工作,遇到了一个问题 implicit 实例。让我们考虑下面的例子:

    import cats.{Applicative, FlatMap, Monad}
    import cats.syntax.functor._
    import cats.syntax.flatMap._
    import cats.syntax.applicative._
    
    
    class Test[F[_]: Monad] extends App{
      val t1 = ().pure[F]
      val t2 = ().pure[F]
    
      def testFlatApplicative: F[Unit] =
        for{
          _ <- t1
          _ <- t2
        } yield ()
    }
    

    这很好。但是自从 cats.Monad[F[_]] 声明如下:

    @typeclass trait Monad[F[_]] extends FlatMap[F] with Applicative[F]
    

    我希望下面的方法也能奏效

    import cats.{Applicative, FlatMap, Monad}
    import cats.syntax.functor._
    import cats.syntax.flatMap._
    import cats.syntax.applicative._
    
    
    class Test[F[_]: FlatMap : Applicative] extends App{
      val t1 = ().pure[F]
      val t2 = ().pure[F]
    
      def testFlatApplicative: F[Unit] =
        for{
          _ <- t1
          _ <- t2
        } yield ()
    }
    

    但它无法编译,出现错误:

    Error:(16, 12) value map is not a member of type parameter F[Unit]
          _ <- t2
    

    这很奇怪。 Apply 延伸 Functor ...

    有人能解释这种行为吗?

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

    class Test[F[_] : FlatMap : Applicative] 脱去糖衣

    class Test[F[_]](implicit flatMap: FlatMap[F], applicative: Applicative[F])
    

    如果你对理解和语法进行分析,你会发现问题:

    def testFlatApplicative: F[Unit] = 
      FlatMap[F].flatMap(t1)(_ => 
        Functor[F].map(t2)(_ => ())
      )
    
    Error: ambiguous implicit values:
     both value applicative in class Test of type cats.Applicative[F]
     and value flatMap in class Test of type cats.FlatMap[F]
     match expected type cats.Functor[F]
    

    因此,您可以手动解决歧义:

    def testFlatApplicative: F[Unit] = 
      FlatMap[F].flatMap(t1)(_ => 
        applicative.map(t2)(_ => ())
      )
    

    def testFlatApplicative: F[Unit] = 
      FlatMap[F].flatMap(t1)(_ => 
        flatMap.map(t2)(_ => ())
      )
    

    当你写作时,没有这样的问题 class Test[F[_]: Monad] 既然你有单隐。