Scala和Haskell中更高的键控类型

时间:2015-01-09 18:45:40

标签: scala haskell higher-kinded-types

Data.Foldable显示以下代数数据类型:

data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)

kind* -> *。它需要a类型。

Prelude> :k Tree
Tree :: * -> *

现在让我们看看trait Foldable[_],一个"更高级的类型"来自Functional Programming in Scala的Scala:

trait Foldable[F[_]] {
  def foldRight[A,B](as: F[A])(z: B)(f: (A,B) => B): B
  ...
}

优秀的书说:

  

就像值和函数具有类型,类型和类型构造函数一样   有种类。 Scala使用种类来跟踪一个类型的类型参数   构造函数需要,......

修改

指定trait Foldable[F[_]]时,F[_]是否始终指示更高级别的类型? F[_]可能是其他什么吗?它可以是一种类型 - F[A]吗?

3 个答案:

答案 0 :(得分:5)

Scala中的F[_]代表Haskell中的* -> *:这是一种“接收”具体类型的类型(Scala中的_和第一个*在Haskell中)并返回一个新的具体类型(F[A]用于某些具体类型A和具体的“容器”F在Scala中)。

是的,F[_]代表某些更高级的类型,例如List[_]Option[_]。在像trait Foldable[A,F[A]]这样的scala中定义遍历是没有用的,因为我们会说Foldable需要使用折叠的特定事物(A)来定义。

答案 1 :(得分:3)

你没有问过很多问题,但是如果你想要一个大概的想法:是的,这两种语言的“善意”系统都是他们自己的类型系统的类型系统。 *类型不是通配符,而是特殊类型的原子; *是“具体类型”的类型,例如String[String]Tree String

反过来有[]Tree(见差异?)之类的内容* -> *;这是“单一参数化类型”的类型,它采用具体类型并产生另一种具体类型。

最后一个例子:有一些名为“monad变形金刚”的东西,如MaybeT,它采用像IO这样的monad,并产生另一个monad,如IO . Maybe(如果你原谅功能的使用)组合经营者,他们通常不被录取)。那是什么类型的?为什么,(* -> *) -> * -> *当然:monad有点* -> *所以我们采用其中一种类型并将其转换为另一种类型。

我不能在Scala语法方面有如此多的专业知识,但在互联网上我们看到Scala中monad变换器特性的定义为:

trait MonadTrans[F[_[_], _]] {
  def lift[G[_] : Monad, A](a: G[A]): F[G, A]
}

所以我认为你的猜测大多是正确的(括号表示一个依赖类型)。

拥有这些事物的类型理论可以保证您永远不会将IO IO之类的东西写成具体类型,或MaybeT String

答案 2 :(得分:2)

F[_] 在该上下文中,即作为类或方法的类型参数,总是意味着更高级的类型,也就是类型构造函数。您也可以将其写为F[A],但通常只有在您要重复使用A来表达约束时才会这样做,例如trait Something[F[A] <: Iterable[A]]

正如书中所说,这种类型限制了什么东西(类型或类型构造函数)可以放在那里。您可以拥有Foldable[List]Foldable[Option],因为这些是单参数类型构造函数,但您不能拥有Foldable[String]Foldable[Either]。同样,您不能拥有Foldable[List[Int]],因为List[Int]是普通类型,例如String(即*种类型)。并且可以具有T[A] = Either[String, A]类型的可折叠,因为它是1参数类型,也就是1参数类型构造函数,也就是类型{{1}虽然你必须使用有点令人难以忍受的语法* -> *来编写它。你可以看到,只有实现给定Foldable[({type T[A]=Either[String, A]})#T]的&#34;类型&#34; (类型构造函数)foldRight具有正确的&#34;形状&#34 ;;如果FF,那么Int会是什么?

F[A]使用不同的scala用法表示存在类型F[_];尽量不要对此感到困惑,他们没有发现。