scala - 如何在 Scala 中定义 HKT for instance (over object) 方法?

标签 scala monads traits higher-kinded-types

如何在 Scala 中定义 HKT 来提供方法,例如 map,作为实例方法而不是对象函数?

我知道你可以

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

object Q extends M[Q] {
  def map[A, B](f: Q[A])(fn: A => B) = new Q(fn(f.e))
}

class Q[A](val e: A)

Q.map(new Q(1))(_.toDouble)

但是,我想在实例上使用 map。我还没有看到任何文献这样做,所以我写了以下内容。

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

class Q[A](val e: A) extends M[A, Q] {
  def map[B](f: A => B) = new Q(f(e))
}

new Q(1).map(_.toDouble)

它是地道的 Scala 吗?它做了 map 应该做的事情吗?与上面的对象版本相比有限制吗? (顺便说一句,使用 extends M[A, Q[A]] 它不会编译 - 为什么?)

我见过

trait M[A] {
  def map[B](f: A => B): M[B]
}

但是 Qmap 可能会返回一个 class R[A] extends M[A],这是不需要的。

最佳答案

有一个专门用于此的库:https://github.com/mpilquist/simulacrum

你也可以自己做。典型的模式是定义相应的隐式 MOps 类或其他类:

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

implicit class MOps[F[_] : M, A](x: F[A]) {
  def map[B](f: A => B): F[B] = implicitly[M[F]].map(x)(f)
}

然后示例用法:

case class Box[A](a: A)

implicit val BoxM = new M[Box] {
  def map[A, B](f: Box[A])(fn: A => B): Box[B] = Box(fn(f.a))
}

Box(2).map(_.toString)

但它有很多样板文件,所以 simulacrum 可以为您(以及更多)完成所有工作。

关于scala - 如何在 Scala 中定义 HKT for instance (over object) 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55407322/

相关文章:

scala - 为什么 `xs reverse_:::ys` 有效?

d - 判断模板参数是否为结构体

groovy - Groovy 特征的菱形继承(钻石问题)

scala - Unresolved 依赖项 : org. scala-tools.sbinary#sbinary_2.9.0;0.4.0:未找到

使用 play dist 出现 java.io.FileNotFoundException

java - 映射目录时 sbt-native-packager 失败并显示 "Too many open files in system"

javascript - 为什么 Promise 是 Monad?

haskell - 将 monad 组合抽象为变压器

haskell - 我如何在 haskell 中抽象这个模式?

generics - 无法访问动态特征实现中的结构字段