【问题标题】:Higher degrees of higher kinded types?更高程度的更高种类的类型?
【发布时间】:2017-11-24 07:53:26
【问题描述】:

我最近才了解更高种类的类型,但我看到的每个示例都只使用了 2 级种类 (* -> *) -> *,例如 Functor

在 Scala 中,使用了一个奇怪的 trait 定义,而在 Haskell 中,使用了 type classes。而且这两种方法似乎都不能再使用一种抽象程度(即((* -> *) -> *) -> *)。

我既不是 Scala 方面的专家,也不是 Haskell 方面的专家,因此如果您能提供此类更高程度类型的简单示例(如果它们完全可以表达的话)将会很有帮助。

【问题讨论】:

  • “这两种方法似乎都不能再多一层抽象”——你为什么这么认为? (顺便说一句:可能更好地关注特征或类型类,而不是两者——它们是完全不同的野兽)。

标签: scala haskell traits typeclass higher-kinded-types


【解决方案1】:

在 Scala(Z) 中,明显的高级类型是 MonadTrans 特征:

trait MonadTrans[F[_ [_], _]] { ... }

它的种类是T->*,其中T是它的参数F的种类。

F 是 monad 转换器,T 是所有 monad 转换器的类型。回想一下,monad 转换器是由一个 monad 参数化的,它的“输出”是另一个 monad,所以它的类型是(*->*) -> (*->*)(或者,等效地,(*->*) -> * -> *)。所以MonadTrans的那种是

((*->*) -> * -> *) -> *

在 Haskell 中没有特征,类型类也不是类型,所以 MonadTrans 是非类型。不过,有一种类型表示单子转换器的组合:

newtype ComposeT f g m a = ...

这是来自Control.Monad.Trans.Compose的完整定义:

newtype ComposeT (f :: (* -> *) -> * -> *) (g :: (* -> *) -> * -> *) m a
    = ComposeT { getComposeT :: f (g m) a }

真是一口! fg 是 monad 转换器(从它们显式给出的签名可以看出),m 是一个 monad(签名 * ->* 没有明确给出,但 g m 暗示),a 是一种常规类型的*。所以ComposeT的整体类型是:

((* -> *) -> * -> *) ->
((* -> *) -> * -> *) ->
 (* -> *) -> * -> *

【讨论】:

    【解决方案2】:
    trait Functor[F[_]] //has kind (* -> *) -> *
    
    trait Functor[A[B[_]]] //has kind ((* -> *) -> *) -> *
    
    trait Map[A[_],B[_]] //has kind (* -> *) -> (* -> *) -> *
    

    编辑:

    您可以通过在 REPL 中调用“kind”命令自行调查种类:

    scala> :kind -v 映射

    【讨论】:

    • 它们是抽象的。这种 Functor 类型不存在,但如果您创建这样的特征,它将具有 kind ((* -> ) -> *) -> * 。并且编译器会注意检查所有 A 类型参数是否具有类型 ( -> *) -> *。像 def doSomething(a: A) 只会用 List(List(1,3)) 之类的值编译
    • 正确。你甚至可以创建具有相同类型 ((* -> *) -> *) -> * 的 trait Functor[ _ [ _ [ _ ] ] ]
    • 是的,它的存在类型。您可以在需要这种类型的任何地方使用,在某些高级情况下,即使需要不同类型(请参阅此问题stackoverflow.com/questions/46263931/…
    • 如果你的方法接受 A 类型,你可以在那里传递所有更高种类的类型,但如果你有 A[ _ ] 你需要完全 * -> * 除了基于 SI-2712 修复的高级用法跨度>
    • 为了澄清,因为我认为没有人在上面的 cmets 中真正回答过它,所以在第二个示例中,A 是一个类型构造函数,它在 Functor 的定义中可见。 B 只是赋予该参数的名称,但仅在 A 的声明范围内。 trait Functor[A[B[_]]] { def b: B[Int] } 无效,但 Functor[A[B[_]] <: B[Int]] 无效。您可以将B 替换为_,如Functor[A[_[_]]],但不能如Functor[A[_[_]] <: _[Int]] 那样,因为这消除了A 的参数和界限之间的关系。类比:trait T[F[X] <: Seq[X]]/trait T[F[_]].
    猜你喜欢
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多