Scala:类型推断和子类型/更高种类的类型

发布于 2024-10-15 21:58:49 字数 1503 浏览 9 评论 0原文

我一直在玩 Scalaz,以便在 scala 中获得一点 Haskell 的感觉。到 了解 scala 中的工作原理 我开始自己实现各种代数结构,并遇到了 Scalaz 人员提到的一种行为。

这是我实现函子的示例代码:

trait Functor[M[_]] {
  def fmap[A, B](a: M[A], b: A => B): M[B]
}

sealed abstract class Foo[+A]
case class Bar[A]() extends Foo[A]
case class Baz[A]() extends Foo[A]

object Functor {

  implicit val optionFunctor: Functor[Option] = new Functor[Option]{
    def fmap[A, B](a: Option[A], b: A => B): Option[B] = a match {
      case Some(x) => Some(b(x))
      case None => None
    }   
  }

  implicit val fooFunctor: Functor[Foo] = new Functor[Foo] {
    def fmap[A, B](a: Foo[A], b: A => B): Foo[B] = a match {
      case Bar() => Bar()
      case Baz() => Baz()
    }   
  }
}

object Main {
  import Functor._

  def some[A](a: A): Option[A] = Some(a)
  def none[A]: Option[A] = None

    def fmap[M[_], A, B](a: M[A])(b: A => B)(implicit f: Functor[M]): M[B] =
      f.fmap(a, b)

  def main(args: Array[String]): Unit = { 
    println(fmap (some(1))(_ + 1)) 
    println(fmap (none)((_: Int) + 1)) 
    println(fmap (Bar(): Foo[Int])((_: Int) + 1))                                                    
  }
}

我为 Option 编写了一个函子实例和一个虚假的 sumtype Foo。问题在于,如果没有显式类型注释或包装器方法,Scala 无法推断出隐式参数。

def some[A](a: A): Option[A] = Some(a)

println(fmap (Bar(): Foo[Int])((_: Int) + 1))

如果没有这些解决方法,Scala 就会推断出 Functor[Bar] 和 Functor[Some] 等类型。

这是为什么?谁能指出我的语言规范中定义此行为的部分吗?

问候, 雷鸟

I've been playing around with Scalaz to get a little bit of the haskell feeling into scala. To
understand how things work in scala I started implementing various algebraic structures myself and came across a behavior that has been mentioned by the Scalaz folks.

Here is my example code which implements a functor:

trait Functor[M[_]] {
  def fmap[A, B](a: M[A], b: A => B): M[B]
}

sealed abstract class Foo[+A]
case class Bar[A]() extends Foo[A]
case class Baz[A]() extends Foo[A]

object Functor {

  implicit val optionFunctor: Functor[Option] = new Functor[Option]{
    def fmap[A, B](a: Option[A], b: A => B): Option[B] = a match {
      case Some(x) => Some(b(x))
      case None => None
    }   
  }

  implicit val fooFunctor: Functor[Foo] = new Functor[Foo] {
    def fmap[A, B](a: Foo[A], b: A => B): Foo[B] = a match {
      case Bar() => Bar()
      case Baz() => Baz()
    }   
  }
}

object Main {
  import Functor._

  def some[A](a: A): Option[A] = Some(a)
  def none[A]: Option[A] = None

    def fmap[M[_], A, B](a: M[A])(b: A => B)(implicit f: Functor[M]): M[B] =
      f.fmap(a, b)

  def main(args: Array[String]): Unit = { 
    println(fmap (some(1))(_ + 1)) 
    println(fmap (none)((_: Int) + 1)) 
    println(fmap (Bar(): Foo[Int])((_: Int) + 1))                                                    
  }
}

I wrote a functor instance for Option and a bogus sumtype Foo. The problem is that scala cannot infer the implicit parameter without an explicit type annotation or a wrapper method

def some[A](a: A): Option[A] = Some(a)

println(fmap (Bar(): Foo[Int])((_: Int) + 1))

Scala infers types like Functor[Bar] and Functor[Some] without those workarounds.

Why is that? Could anyone please point me to the section in the language spec that defines this behavior?

Regards,
raichoo

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

愛上了 2024-10-22 21:58:49

您要求编译器执行两项任务:fmap 的类型参数的本地类型推断 (§6.26.4),以及隐式搜索隐式参数 (§7.2) f< /代码>。参考内容为 Scala 参考

事情大致按以下顺序进行:

fmap[M = ?, A = ?, B = ?](Some(1))(x => x)

// type the arguments of the first parameter section. This is done
// without an expected type, as `M` and `A` are undetermined.
fmap[M = ?, A = ?, B = ?](Some(1): Some[Int])(x => x)(?) 

// local type inference determines `M` and `A`
fmap[Some, Int, B = ?](Some(1): Some[Int])(x => x)(?) 

// move to the second parameter section, type the argument with the expected type
// `Function1[Int, ?]`. The argument has the type `Function1[Int, Int]`
fmap[Some, Int, ?](Some(1): Some[Int])((x: Int) => x)                                                 

// local type inference determines that B = Int
fmap[Some, Int, Int](Some(1): Some[Int])((x: Int) => x)

// search local identifiers, and failing that the implicit scope of type `Functor[Some]]`, for an implicit
// value that conforms to `Functor[Some]`
fmap[Some, Int, Int](Some(1): Some[Int])((x: Int) => x)(implicitly[Functor[Some]])

Functor[Some] 的隐式搜索失败; Functor[Option] 不符合要求。

You're asking the compiler to perform two tasks: local type inference (§6.26.4) of the type arguments to fmap, and an implicit search for implicit parameter (§7.2) f. References are to the Scala Reference.

Things go in roughly this order:

fmap[M = ?, A = ?, B = ?](Some(1))(x => x)

// type the arguments of the first parameter section. This is done
// without an expected type, as `M` and `A` are undetermined.
fmap[M = ?, A = ?, B = ?](Some(1): Some[Int])(x => x)(?) 

// local type inference determines `M` and `A`
fmap[Some, Int, B = ?](Some(1): Some[Int])(x => x)(?) 

// move to the second parameter section, type the argument with the expected type
// `Function1[Int, ?]`. The argument has the type `Function1[Int, Int]`
fmap[Some, Int, ?](Some(1): Some[Int])((x: Int) => x)                                                 

// local type inference determines that B = Int
fmap[Some, Int, Int](Some(1): Some[Int])((x: Int) => x)

// search local identifiers, and failing that the implicit scope of type `Functor[Some]]`, for an implicit
// value that conforms to `Functor[Some]`
fmap[Some, Int, Int](Some(1): Some[Int])((x: Int) => x)(implicitly[Functor[Some]])

The implicit search for Functor[Some] fails; Functor[Option] doesn't conform.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文