2017-09-01 305 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