2016-04-28 7 views
0

a small Scala utility libの異種リスト再帰型を構築しようとしています。 私は2つのHlistを連結し、一貫した型を保つ問題があります。実行時に型がOKになるよう Scala再帰型の問題(Hlistを構築するため)

trait HList { 
    def ::[U](v: U): HList 
} 

class HNil extends HList { 
    override def ::[T](v: T) = HCons(v, this) 
}  

case object HNil extends HNil 

case class HCons[T, U <: HList](head: T, tail: U) extends HList { 

    def ++[V <: HList, R <: HList](l2: V): HCons[T, R] = { 
    def append(l1: HCons[T, _], l2: V): HCons[T, _] = { 
     l1.tail match { 
     case HNil => HCons(l1.head, l2) 
     case h: HCons[T, U] => l1.head :: append(h, l2) 
     } 
    } 
    append(this, l2) match { 
     case h: HCons[T,R] => h 
    } 
    } 
} 

これ

は、働いている:

val sum = (2.0 :: "hi" :: HNil) ++ (1 :: HNil) 
sum shouldBe 2.0 :: "hi" :: 1 :: HNil 
sum shouldBe a[HCons[_, HCons[_, HCons[_, HNil]]]] 

しかし、次のコードはコンパイルされません。

val sum = (2.0 :: "hi" :: HNil) ++ (1 :: HNil) 
sum.tail.head 

value head is not a member of Nothing

は、あなたが知っていますかsum.tail、すなわちHCons [Int、HNil]の正しい型を選択するようにコンピュータに指示する方法?

感謝:)

答えて

1

基本的には、コンパイラは、単に引数の型から結果型Rを決定することはできません。見ていると、実際にコードを決定するコードはありません。したがって、コンパイラはNothingを選択します。

この問題を回避するには、Appenderタイプのクラスを持つ内部型を使用することが最も簡単な解決策であると考えています。HConsのように実装するためにまっすぐ進むのではなく、

完全なソリューションがここにある私のことができるようになるよりもはるかに優れたアップ書か:http://jnordenberg.blogspot.co.uk/2008/08/hlist-in-scala.html

+0

おかげで、確かに私の現在のバージョンはこのブログに触発されたものを使用しています:)富栄私はそれで他の問題を持って、私は私がすると思いますそれについて別の質問を開いてください:) – Loic

+0

私の新しい問題:D http://stackoverflow.com/q/36945476/591922 – Loic

関連する問題