2016-09-30 18 views
1

I以下の方法があります。型崩れ:複雑なHList制約

import shapeless._ 
import shapeless.UnaryTCConstraint._ 
def method[L <: HList : *->*[Seq]#λ](list: L) = println("checks") 

それは私が次の問題が発生したことを確認することができます:私は別のパラメータリストでmethodを強化するにはどうすればよい

val multipleTypes = "abc" :: 1 :: 5.5 :: HNil 
val onlyLists = Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil 

method(multipleTypes) // throws could not find implicit value ... 
method(onlyList) // prints checks 

を、のようなもの:

def method2[L <: HList : *->*[Seq]#λ, M <: HList](list: L)(builder: M => String) = println("checks") 

ただし、HList MはHList L aと同じサイズでなければならないという制限があります

// This should work 
method2(Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil){ 
    case a :: 1 :: d :: HNil => "works" 
} 
// This should throw some error at compile time, because the second element is Seq[Int] 
// therefore in the builder function I would like the second element to be of type Int. 
method2(Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil){ 
    case a :: true :: d :: HNil => "fails" 
} 
// This should also fail because the HLists are not of the same length. 
method2(Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil){ 
    case 1 :: d :: HNil => "fails" 
} 

私はこのようmethod2を定義する場合:

def method2[L <: HList : *->*[Seq]#λ](list: L)(builder: L => String) = println("checks") 

それはほとんど問題、唯一の解決だけで私は例をあげてみようHList L.の内側の種類の要素が含まれているNDタイプBの要素の代わりにタイプSeq [T]の要素を持つことになります。

+0

'法2(配列(「ABC」、「DEF」)の結果がどうあるべきか::配列(1、 2,3):: Seq(5.5):: HNil){case a :: b :: c :: HNil => a.toString + b.toString + c.toString} '? – Kolmar

+0

HListのサイズが同じで、a、b、cの型に制限がないので正しく動作するはずです。したがって、それらは正しく 'String'、' Int'、 'Double'であると推測されるべきです。 –

答えて

2

これはops.hlist.Comappedの場合です。

あなたはタイプMbuilder引数を型チェックする前に計算する必要がありますので、method2

として
def method2[L <: HList : *->*[Seq]#λ, M <: HList] 
    (list: L) 
    (builder: M => String) 
    (implicit ev: Comapped.Aux[L, Seq, M]) 

を定義する。しかし、これは動作しませんしたいと思います。

だから、実際の実装は次のようになり:

class Impl[L <: HList : *->*[Seq]#λ, M <: HList] 
    (list: L) 
    (implicit ev: Comapped.Aux[L, Seq, M]) 
{ 
    def apply(builder: M => String) = println("checks") 
} 

def method2[L <: HList : *->*[Seq]#λ, M <: HList] 
    (list: L) 
    (implicit ev: Comapped.Aux[L, Seq, M]) = new Impl[L, M](list) 

そして、あなたはそれを直接呼び出すことはできません。あなたはapply追加、または暗黙的に暗黙の引数リストを提供するために、いくつかの他の方法を使用することができます:

method2(Seq("abc") :: Seq(1) :: Seq(5.5) :: HNil) apply { 
    case a :: 1 :: d :: HNil => "works" 
}