2017-09-01 124 views
1

我实现了一个TList,可以收集任何类型的H。但我发现它不能包含更高订单类型H[_]。所以我拷贝了整个东西,并把[_]添加到尊重的地方。如何抽象类型类型?

虽然出现在我的脑海里。如果我需要存储H[_[_]],H[_[_,_]]甚至H[_[_[_]]],该怎么办?我应该随时复制代码吗?有没有什么方法可以抽象出类型的好意?

+1

认为您正在寻找:https://underscore.io/blog/posts/2016/12/05/type-lambdas.html。你也可以展示你到目前为止? – pedromss

+0

没什么特别的,就像正常的无形练习。尽管如此,类型lambdas仍然会键入类型。它允许'*,* - > *'到'* - > *'¸,但它无法编写容易同时接受'*','* - > *','* - > * - > *' – ayvango

+0

不,但它有助于编写使用具有特定数量类型的类型的could。我所说的是,而不是重复执行改变你使用它的方式。你的一个片段'TList'和几个你想达到的例子会有所帮助。 – pedromss

回答

1

在Scala中没有rank-2多态性。它意味着方法(除此之外甚至不是多态的函数)除了具有通用量词的参数之外不能(除了方法级别的所有通用量化)。因此,我们可以有一个像

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])。

但是为了让类型和类型构造函数看起来更加一致,你可以使用特征类型来包装一个类型构造函数。例如,你可以看看下面的编码(这是肯定罗嗦,你必须包装,拆开包装类型所有的时间):

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/

+1

我习惯于这样的结构:'[X,U [_ <:X],H [Y <:X] <:U [Y ]]'。它看起来非常难看,特别是当它连续发生两次时 – ayvango