ここで同様の質問がいくつかあります。私はそれらを読んで、自分のコードが動作するような答えは見つけられませんでした。私は、通常よりも正確な型指定を必要とするコーナーケースに当たったと思います。f-bound多型型の存在を正しく定義する方法
私の場合は2単語です。私はスカラ言語の理解を深めるために非常にシンプルな異種リストの例を作りたいと思っています。私が自分自身に設定した制限があります。どんな形でも暗黙の意味はなく、ただのスカラ型システムです。 Implicitsは多くのことを簡単にすることができますが、私は頑張ります。
私はすでにコードを作業していますが、改善したいと思います。ここでは、次のとおりです。
sealed trait HList {
type Self <: HList
def self : Self
def prepend[H](head : H) = HCons[H, Self](head, self)
def ::[H](head : H) = prepend(head)
type Merge[X <: HList] <: HList
def merge[X <: HList](other : X) : Merge[X]
def :::[X <: HList](other : X) = other.merge[Self](self)
}
sealed trait HNil extends HList {
override type Self = HNil
override def self = this
override type Merge[X <: HList] = X
override def merge[X <: HList](other : X) : Merge[X] = other
}
case object HNil extends HNil
final case class HCons[H, T <: HList](head : H, tail : T) extends HList {
override type Self = HCons[H,T]
override def self = this
override type Merge[X <: HList] = HCons[H, T#Merge[X]]
override def merge[X <: HList](other : X) : Merge[X] = HCons(head, tail.merge(other))
}
Merge
型コンストラクタは二つのリストを追加するタイプの結果を示しています。すべてのネストされた型を追跡する必要があります。結果は次のとおりです。
val x = "str" :: true :: HNil
val s : String = x.head
val b : Boolean = x.tail.head
val y = 0.5 :: 12 :: HNil
val d : Double = y.head
val i : Int = y.tail.head
val l = x ::: y
val r = y.merge(x)
val sl : String = l.head
val sb : Boolean = l.tail.head
val sd : Double = l.tail.tail.head
val si : Int = l.tail.tail.tail.head
val rd : Double = r.head
val ri : Int = r.tail.head
val rl : String = r.tail.tail.head
val rb : Boolean = r.tail.tail.tail.head
私は退屈な紹介をしました。私はその点まで読者の半分を失ってしまったのだろうかと思います。私は、コードを一行にまとめてもいいと思っています。
実際の問題はSelf
タイプとself
メソッドです。彼らは醜く見え、私はそれらを取り除きたい。私はfの束縛された多型が自然な方法でそれを助けることができると信じています。私は、次のコードを取得する:スムーズF結合多型に変換
[error] App.scala:23: type arguments [H,T#Merge[X]] do not conform to method apply's type parameter bounds [H,T <: SelApp1.this.HList[T]]
[error] override def merge[X <: HList[X]](other : X) : Merge[X] = HCons[H, T#Merge[X]](head, tail.merge(other))
[error] ^
[error] one error found
プリペンド一部:
type HAny = X forSome {type X <: HList[X]}
sealed trait HList[Self <: HList[Self]] {this : Self =>
def prepend[H](head : H) = HCons[H, Self](head, this)
def ::[H](head : H) = prepend(head)
type Merge[X <: HList[X]] <: HAny
def merge[X <: HList[X]](other : X) : Merge[X]
def :::[X <: HList[X]](other : X) = other.merge[Self](this)
}
sealed trait HNil extends HList[HNil] {
override type Merge[X <: HList[X]] = X
override def merge[X <: HList[X]](other : X) : Merge[X] = other
}
case object HNil extends HNil
final case class HCons[H, T <: HList[T]](head : H, tail : T) extends HList[HCons[H,T]] {
override type Merge[X <: HList[X]] = HCons[H, T#Merge[X]]
override def merge[X <: HList[X]](other : X) : Merge[X] = HCons[H, T#Merge[X]](head, tail.merge(other))
}
Scalaのコンパイラは私に非常に少し洞察力を与えるエラーが発生します。マージ部分でエラーが発生しました。私はMerge
型を抽象化する必要があるので、HAny
実在型と結びつけました。私はHList
を追加の型指定なしで使用しました。
しかし、後者の場合、コンパイラが不適切な型について文句を言うので、いくつかの型情報が失われます。では、ビルドに必要なすべてのタイプ情報を保持するために、存在タイプをどのように定義できますか?HCons
?おそらく、抽象型の解をfバウンドバリアントに移すためには、もっと複雑な調整が必要でしょうか?
フェデリコ、これはそれが動作面で素晴らしい答えですが、元のコードはdoesnの理由のいくつかの詳細を提供してください可能性これはどうですか?重大な違いはどこですか?私はこのトリックを、必要なときに再び複製できるように理解しているとは思わない。 – SergGr