这个问题在这里已有答案:
我正在阅读Scala书中的函数式编程和Monoids章节,他们讨论了一个如下所示的Monoid接口:
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
稍后,他们通过扩展此接口来定义特定的Monoid实例 . 例如 . ,
val intMonoid = new Monoid[Int] {
...
}
val listMonoid = new Monoid[List[Int]] {
...
}
我通过本章10阅读了几页,我遇到了“更高级的类型”,根据这本书,它是任何类型,它本身就是一种可以采用其他类型的类型 .
trait Foldable[F[_]] {
...
...
}
因此,可折叠的特性是根据书中较高的一种类型 . 我的问题是,Monoid [A]对我来说也适合'更高的kinded类型'定义,因为它可以采用List [A] . 我的理解是否正确?如果不是什么使更高的kinded类型在Scala中成为更高的kinded类型?
编辑:所以一元类型构造函数接受一个参数并生成一个类型 . 那么这个案子呢?
def listMonoid[A] = new Monoid[List[A]] {
...
...
}
那么我的listMonoid函数是HKT吗?
1 回答
一些术语:
正确类型(例如Int)
一阶类型(例如List [_]);我们也可以说是一流的
更高级的类型(例如Monad [M [_])
当你说
你正在使用某种类型A参数化
Monoid
特征,它可以(如你所注意到的)是一个简单类型,也称为正确类型(例如Int
)或参数化类型(例如List[Int]
,甚至List[Set[Map[Int, Int]]
) . 这使Monoid
成为一阶类型 . 我们也可以说它是一个一元类型的构造函数 - 它需要一种类型来生成最终类型 .与Monoid不同,某些抽象(例如Monad)需要通过类型构造函数进行参数化 . Int不再起作用了 . 它必须是"some type than can produce another type" . 由类型构造函数(即,由"first-order type"参数化)参数化的抽象是更高级的类型 . 这是一个例子:
所以
Monad
由一阶类型(一元类型构造函数)参数化,这使Monad
本身成为一种更高级的类型 .注意
Monad
在类级别上并不真正关心"inner type"本身,因为它将由方法op
和zero
定义 . 您也可以在类ListMonad
的定义点上说trait Monad[M[A]]
和"fix"类型A(例如将其修复为Int),但是您失去灵活性(您的ListMonad
将只能构造和平面图List[Int]
并且您需要例如,List[String]
)的另一个类 .这与Monoid不同,Monoid不是更高级的类型;它不需要类型构造函数来生成类型 . 如果需要它,那么你可能永远不会有
Monoid[Int]
,因为Int不是类型构造函数 .它是一种单向关系 - 如果你有一个简单的类型A,它代表任何类型的任何顺序,所以在这种情况下
List[Int]
可以作为一个非常好的A
(所以List[Set[Option[Try[Int]]]]
也可以 . 但如果你有一阶输入M [A],你不能把它变成一个简单的具体类型,如Int . 它需要是一个类型构造函数.Monoid可以使用Ints,但是Monad不能; monad需要有一些"container",如Option[_]
,Try[_]
,List[_]
,Set[_]
等 . 这就像子类型 - 香蕉可以作为水果,但水果不能作为香蕉 . 适当的类型可以是任何东西;一阶类型需要一种类型来 生产环境 一种类型;更高级的类型需要一个生成类型的一阶类型,依此类推 .它's also important to note that it'是一个一元类型的构造函数,意味着它只需要一种类型(不像例如Map需要两种类型) . 类型构造函数通常用星号和箭头表示:
一元一阶类型构造函数是
* -> *
(它采用单一类型并生成最终类型,例如Set)二进制一阶类型构造函数是
* -> * -> *
(二进制类型构造函数,需要两种类型来生成最终类型,例如Map)一元高级类型是
(* -> *) -> *
(采用单个一元类型构造函数来生成最终类型,例如Monad)等等
因此,一阶类型采用简单/具体/适当的类型并产生最终类型,而高级类型采用上一级;它采用一阶类型来生成最终类型 .
EDIT:
在"edit"中回答你的问题:好的我想我知道你有什么困惑 .
listMonoid
不是一个类型,所以它可以't be a higher-kinded type. It'是一个方法 .Monad[List[Int]]
是完全解析的类型 .Monad[F[A]]
也完全解决了 . 但是,Monad
本身是更高阶的类型 .让我拉动并行功能 . 如果你有一个函数
foo(x: Int)
,那么函数调用如foo(42)
或foo(someIntegerValue)
会产生具体的值 . 这些类似于Monad[List[Int]]
和Monad[F[A]]
. 但是,foo
本身就是一个函数,就像Monad
本身就是一个类型构造函数 .如果
foo
采用简单值(不是函数),则's a first-order function; if it takes or returns a function, then it'是高阶函数 . 与类型构造函数相同 . 如果它采用简单类型,则它是一阶类型构造函数 . 示例:List
. 如果它需要另一种类型的构造函数,它是一个更高阶的类型构造函数(也称为更高级的类型) . 示例:Monad
.不要将已解析的类型与类型构造函数混合 . 认为函数
foo
是否为高阶是有意义的;这取决于它的参数和返回类型 . 但是,认为foo(42)
是否为高阶是没有意义的;这不是一个函数,而是一个函数应用程序,它会产生 Value .Monad[List[Int]]
不是类型构造函数,而是类型构造函数List
的应用程序,类型构造函数Monad
(高阶) . 类似地,Monoid[List[Int]]
不是类型构造函数,而是类型构造函数Monoid
(它是一阶)的类型List[Int]
的应用程序 . 高阶类型构造函数称为HKT . 谈论HKT并指出具体解决的类型(由于应用某种类型的构造函数而创建)是没有意义的 .