spa*_*rkr 2 scala higher-kinded-types monoids
我正在阅读Scala书中的函数式编程和Monoids章节,他们讨论了一个如下所示的Monoid接口:
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
Run Code Online (Sandbox Code Playgroud)
稍后,他们通过扩展此接口来定义特定的Monoid实例.例如.,
val intMonoid = new Monoid[Int] {
...
}
val listMonoid = new Monoid[List[Int]] {
...
}
Run Code Online (Sandbox Code Playgroud)
我通过本章10阅读了几页,我遇到了"更高级的类型",根据本书,它是任何类型,它本身就是一种可以采用其他类型的类型.
trait Foldable[F[_]] {
...
...
}
Run Code Online (Sandbox Code Playgroud)
因此,可折叠的特性是根据书中较高的一种类型.我的问题是,Monoid [A]对我来说也符合'更高的kinded类型'定义,因为它可以采用List [A].我的理解是否正确?如果不是什么使得更高级的kinded类型在Scala中成为更高的kinded类型?
编辑:所以一元类型构造函数接受一个参数并生成一个类型.那么这个案子呢?
def listMonoid[A] = new Monoid[List[A]] {
...
...
}
Run Code Online (Sandbox Code Playgroud)
那么我的listMonoid函数是HKT吗?
一些术语:
当你说
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
val listMonoid = new Monoid[List[Int]] {
def op(l: List[Int], l2: List[Int]) = List(1,2)
def zero = List(1,2)
}
Run Code Online (Sandbox Code Playgroud)
你正在Monoid使用某种类型A 来参数化特征,它可以(如你所注意到的)是一个简单类型,也可以称为正确类型(例如Int)或参数化类型(例如List[Int],甚至List[Set[Map[Int, Int]]).这是Monoid一阶类型.我们也可以说它是一个一元类型的构造函数 - 它需要一种类型来生成最终类型.
与Monoid不同,某些抽象(例如Monad)需要通过类型构造函数进行参数化.Int不再起作用了.它需要"某种类型而不能产生另一种类型".由类型构造函数参数化的抽象(即,由"一阶类型"参数化)是更高级的类型.这是一个例子:
trait Monad[M[_]] {
def op[A, B](m: M[A], f: A => M[B]): M[B]
def zero[A](a: A): M[A]
}
object ListMonad extends Monad[List] {
def op[A, B](m: List[A], f: A => List[B]) = m.flatMap(f)
def zero[A](a: A) = List[A](a)
}
val listMonad = ListMonad.zero(42)
val result = ListMonad.op(listMonad, (i: Int) => List(i - 1, i, i + 1))
// result = List(41, 42, 43)
Run Code Online (Sandbox Code Playgroud)
因此Monad,通过一阶类型(一元类型构造函数)进行参数化,这使其Monad自身成为更高级的类型.
注意如何Monad在类级别上真正关心"内部类型"本身,因为它将由方法op和zero.你也可以trait Monad[M[A]]在类的定义点上说"修复"类型A ListMonad(例如将其修复为Int),但是你失去了灵活性(那时你ListMonad只能构造和平面映射a List[Int]你需要一个不同的比如说,List[String]等等.
这与Monoid不同,Monoid不是更高级的类型; 它不需要类型构造函数来生成类型.如果它需要它,那么你可能永远不会有,比如说Monoid[Int],因为Int不是一个类型构造函数.
还要注意我是怎么说Monad需要一个一元类型的构造函数,这意味着它只需要一种类型(不像例如Map需要两个).类型构造函数通常用星号和箭头表示:
* -> *(它采用单一类型并生成最终类型,例如Set) * -> * -> *(二进制类型构造函数,需要两种类型来生成最终类型,例如Map) (* -> *) -> *(采用单一的一元类型构造函数来生成最终类型,例如Monad) 等等
因此,一阶类型采用简单/具体/适当类型并产生最终类型,而高级类型采用上一级; 它采用一阶类型来生成最终类型.
编辑:
在"编辑"部分回答你的问题:好的我想我知道你有什么困惑.listMonoid不是一种类型,所以它不能是一种更高级的类型.这是一种方法.Monad[List[Int]]是完全解析的类型.Monad[F[A]]也完全解决了.但是,Monad它本身是一种更高阶的类型.
让我拉动并行功能.如果你有一个函数foo(x: Int),那么函数调用foo(42)或foo(someIntegerValue)导致具体的值.这些类似于Monad[List[Int]]和Monad[F[A]].但是,foo它本身就是一个函数,就像Monad它本身就是一个类型构造函数一样.
如果foo采用简单值(不是函数),则它是一阶函数; 如果它接受或返回一个函数,那么它是一个高阶函数.与类型构造函数相同.如果它采用简单类型,则它是一阶类型构造函数.示例:List.如果它需要另一个类型构造函数,它是一个高阶类型构造函数(也称为高级类型).示例:Monad.
不要将已解析的类型与类型构造函数混合.认为功能是否foo为高阶是有意义的; 这取决于它的参数和返回类型.但是,思考是否foo(42)是高阶是没有意义的; 这不是一个函数,而是一个函数应用程序,它会产生价值.Monad[List[Int]]不是类型构造函数,而是类型构造函数的应用程序List到类型构造函数Monad(高阶).类似地,Monoid[List[Int]]不是List[Int]类型构造函数,而是类型构造函数的类型应用程序Monoid(它是一阶的).高阶类型构造函数称为HKT.谈论HKT并指出具体解决的类型(由于应用某种类型的构造函数而创建)是没有意义的.
| 归档时间: |
|
| 查看次数: |
884 次 |
| 最近记录: |