Data.Foldable显示以下代数数据类型:
data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)
它 kind
是 * -> *
. 它需要 a
类型 .
Prelude> :k Tree
Tree :: * -> *
现在让我们看看来自Functional Programming in Scala的Scala的 trait Foldable[_]
,"higher-kinded type":
trait Foldable[F[_]] {
def foldRight[A,B](as: F[A])(z: B)(f: (A,B) => B): B
...
}
这本优秀的书说:
就像值和函数具有类型,类型和类型构造函数一样 . Scala使用种类来跟踪类型构造函数采用的类型参数的数量,...
EDIT
指定 trait Foldable[F[_]]
时, F[_]
是否始终指示较高的类型?是否有可能 F[_]
是其他什么?可能是一种类型 - F[A]
?
3 回答
Scala中的
F[_]
代表Haskell中的* -> *
:这是一种"receives"具体类型(Scala中的_
和Haskell中的第一个*
)并返回一个新的具体类型(F[A]
用于某些具体类型A
和具体"container"F
在斯卡拉) .所以,是的,
F[_]
代表一些更高的kinded类型,如List[_]
或Option[_]
. 在像trait Foldable[A,F[A]]
这样的scala中定义遍历是没有用的,因为我们会说Foldable
需要定义特定的东西被折叠(A
) .你没有问过很多问题,但是如果你想要一个大概的想法:是的,这两种语言的"kind"系统都是他们自己的类型系统的类型系统 .
*
类型不是通配符,而是特殊类型的原子;*
是"concrete types"的类型,如String
,[String]
和Tree String
.反过来有
[]
或Tree
(见区别?)的东西* -> *
;这是"singly-parametrized types"的类型,它采用具体类型并生成另一种具体类型 .最后一个例子:有一些名为"monad transformers"的东西,如
MaybeT
,它采用像IO
这样的monad,并生成另一个monad,如IO . Maybe
(如果你原谅我们一般不承认使用函数组合运算符) . 那是什么类型的?为什么,(* -> *) -> * -> *
当然:monad有点* -> *
所以我们采用其中一种类型并将其转换为另一种类型 .我不能在Scala语法方面有如此多的专业知识,但在Internet上我们在Scala中看到了monad变换器特性的定义:
所以我认为你的猜测大多是正确的(括号表示一个依赖类型) .
拥有这些东西的类型理论可以保证你永远不会把
IO IO
这样的东西写成具体的类型,或者MaybeT String
.F[_]
在该上下文中,即作为类或方法的类型参数,总是意味着更高级的类型,也就是类型构造函数 . 您也可以将其写为F[A]
,但通常只有在您重复使用A
来表达约束时才会这样做,例如trait Something[F[A] <: Iterable[A]]
.正如书中所说,这种类型限制了可以放置的东西(类型或类型构造函数) . 您可以拥有
Foldable[List]
或Foldable[Option]
,因为这些是1参数类型构造函数,但您不能拥有Foldable[String]
或Foldable[Either]
. 同样,你不能拥有Foldable[List[Int]]
,因为List[Int]
是一个普通的类型,如String
(即善良*
) . 并且您可以为T[A] = Either[String, A]
类型设置折叠,因为这是一个1参数类型,也就是1参数类型构造函数,也就是类型* -> *
,尽管您必须使用有点难以理解的语法Foldable[({type T[A]=Either[String, A]})#T]
来编写它 . 并且您可以看到只有为具有正确"shape"的"types"(类型构造函数)F
实现给定foldRight
才有可能;如果F
是Int
,那么F[A]
会是什么?F[_]
的不同scala用法表示存在类型,F[A] forSome { type A }
;尽量不要对此感到困惑,他们没有发现 .