本文介绍了如何抽象类型类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实现了一个 TList 可以收集任何类型的 H.但是我发现它不能包含高阶类型H[_].所以我复制了整个内容并将 [_] 添加到受人尊敬的地方.

I implemented an TList that could collect any type H. But I've discovered that it could not contain higher order types H[_]. So I copypasted the entire thing and added [_] to respected places.

虽然我想到了.如果我需要存储 H[_[_]]H[_[_,_]] 甚至 H[_[_[_]]]].我应该随时复制代码吗?有没有办法抽象类型善意?

The though came to my mind. What if I would need to store H[_[_]], H[_[_,_]] or even H[_[_[_]]]. Should I just copy the code any time? Is there any way to abstract over type kindness?

推荐答案

在 Scala 中没有 2 级多态.这意味着方法(以及根本不是多态的函数)不能除了带有全称量词的参数(所有全称量词都应该在方法级别上完成).所以我们可以有像

In Scala there is no rank-2 polymorphism. It means methods (and moreover functions which are not even polymorphic at all) can't except arguments with universal quantifiers (all universal quantifications should be done on method level). So we can have methods like

def f[A, B[_], C[_[_]]](x: A, y: B[A], z: C[B]) = ???

但不喜欢(伪代码)

def f(x: [A] A, y: [A1, B[_]] B[A1], z: [B1[_], C[_[_]]] C[B1]) = ???

这也意味着我们不能将类型构造函数替换为期望特定类型的地方(实际上,类型构造函数 B[_] 可以被视为 [A] B[A], C[_[_]]][B[_]] C[B][[A] B[A]] C[B]).

Also this means we can't substitute type constructor to the place where a specific type is expected (really, a type constructor B[_] can be considered as [A] B[A], C[_[_]]] as [B[_]] C[B] or [[A] B[A]] C[B]).

但是为了使类型和类型构造函数看起来更统一,您可以使用 trait 类型包装类型构造函数.例如,您可以查看以下编码(它肯定很罗嗦,您必须一直包装-解包类型):

But to make types and type constructors look more uniformly you can wrap a type constructor with a trait type. For example you can look at the following encoding (it's surely wordy, you have to wrap-unwrap types all the time):

  trait Type

  trait ConcreteType extends Type {
    type T
  }

  trait TypeConstructor[U] extends Type {
    type l[X <: U] <: ConcreteType
  }

  type Type0 = ConcreteType
  type Type1 = TypeConstructor[Type0]
  type Type2 = TypeConstructor[Type1]
  type Type3 = TypeConstructor[Type2]

//  type A = Int

  type A = Type0 {type T = Int}

//  type B[X] = List[X]

  type B = Type1 {
    type l[X <: Type0] = Type0 {type T = List[X#T]}
  }

  trait Functor[F[_]]

//  type C[F[_]] = Functor[F]

  type C = Type2 {
    type l[F <: Type1] = Type0 {
      type T = Functor[
        ({
          type ll[X] = (F#l[Type0 {type T = X}])#T
        })#ll
        ]
    }
  }


  trait Generic[FF[_[_]]]   // like shapeless.Generic1, shapeless.IsHCons1, shapeless.IsCCons1
  // Generic1[F[_], FR[_[_]]], IsHCons1[L[_], FH[_[_]], FT[_[_]]], IsCCons1[L[_], FH[_[_]], FT[_[_]]]
  // Generic1[F, Functor], IsHCons1[L, Monad, Monad], IsCCons1[L, Applicative, Applicative]

//  type D[FF[_[_]]] = Generic[FF]

  type D = Type3 {
    type l[FF <: Type2] = Type0 {
      type T = Generic[
        ({
          type ll[F[_]] = (
            FF#l[Type1 {
              type l[X <: Type0] = Type0 {type T = F[X#T]}
            }]
            )#T
        })#ll
        ]
    }
  }

  import shapeless.{::, HNil}

  type lst = A :: B :: C :: D :: HNil

一些链接:

https://wiki.haskell.org/Rank-N_types

https://en.wikibooks.org/wiki/Haskell/Polymorphism#Higher_rank_types

https://apocalisp.wordpress.com/2010/07/02/higher-rank-polymorphism-in-scala/

这篇关于如何抽象类型类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 16:15