Scala:用一些通用类型制作更高种类的类型

标签 scala functional-programming monads higher-kinded-types

例如,我定义了一个 Monad Trait,如下所示:

trait Monad[F[_]] {
  def unit[T](a: => T): F[T]
  def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}

我创建了一个实现上述接口(interface)的 ListMonad:

 class ListMonad extends Monad[List] {
    override def unit[T](a: => T): List[T] = List(a)

    override def flatMap[A, B](fa: List[A])(f: (A) => List[B]): List[B] = fa flatMap f
  }

现在我想以“通用方式”验证上面的 Monad。 monad 的第一个属性是Left Identity。这意味着:如果我们给一个单子(monad)“m”,一个值“x”和一个函数“f”。它应该满足:m.(identity(x)).flatMap(f) == f(x)

例如,我创建了以下验证器类来检查该假设:

case class MonadVerifier[A, F[_]](monad: Monad[F[_]])(f: A => F[A]) {
  def leftIdentity(value: A): Boolean =
    monad.flatMap[A, A](monad.unit(value))(f) == f(value)
}

在这段代码中,我遇到了错误:

Type mismatch. expected: (A) => F[_][A], actual: (A) => F[A]

我不知道在 Scala 中,如何将 F[A] 表示为泛型。我想如果我定义了 F[_] Scala 会在调用 F[A] 时将泛型类型插入到 [_] 中,但事实并非如此真的。

在这种情况下请帮助我。谢谢

最佳答案

@Dima 说的:

错误是

MonadVerifier[A, F[_]](monad: Monad[F[_]])

应该是

MonadVerifier[A, F[_]](monad: Monad[F])

第一行不是说 F 是一个 monad(F 有种类 * -> * 类型的值code>F[_]),但是 F[_](即类型构造函数 F 应用于任何正确类型的类型)是一个monad,(F 具有类型 * -> (* -> *) 和类型 F[_][_] 的值)。

对此进行扩展(如果需要,请忽略此内容):Monad 期望其类型参数采用一个类型参数并返回一个具体类型。 Monad 的参数据说具有种类 * -> *(从具体类型到具体类型的“函数”),并且 Monad 本身具有kind (* -> *) -> * (“函数”来自“函数”,从具体类型到具体类型再到具体类型)。当你说 Monad[F[_]] 时,你暗示参数 (F[_]) 具有种类 * -> *,因为那是 Monad 期望的那种。 F[_] 是类型构造函数 F 的应用(kind a -> b 对于一些未知类型 ab) 到任何具体类型(由 _ 暗示,强制 F 的种类被限制为 * -> k 对于一些未知的 k)。由于 F[_] 也必须是 * -> * 因为 Monad,这限制了 k = (* -> * ) 所以 F 被强制为 * -> (* -> *) 类型,这是 (*, * ) -> *。这意味着 F 有两个类型参数,并且在第二个参数中它是单子(monad)的(如 Either)。

将来,可能会使用上下文绑定(bind)来避免类似的混淆:

MonadVerifier[A, F[_]: Monad] // no params needed

关于Scala:用一些通用类型制作更高种类的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44929406/

相关文章:

scala - 带有集成测试的 sbt 组装

scala - 是否需要调用 Future 方法参数 "by-name"?

javascript - ImmutableJS - 过滤嵌套 Map{List(Map{...})}

haskell - 为什么在 monad 中使用如此奇特的函数类型?

list - 如何使用惯用的 Scala 从另一个列表中替换(填充)选项列表中的无条目?

scala - 如何让 sbt 使用 $SCALA_HOME 目录中的 scala 二进制文件?

functional-programming - Ramda 的类型注解中的 Ord 是什么意思?

javascript - Typescript 中的闭包(依赖注入(inject))

oop - Haskell - 状态单子(monad)是命令式思维的标志吗?

c# - 这是计算表达式的候选者吗?