2

String を Integer に変換できる型依存の Converter 型クラスがあるとします。

trait Converter[From] {
  type To
  def to(from: From): To
}

object Converter {
  type Aux[From, Out0] = Converter[From] { type To = Out0 }

  implicit val forInteger = new Converter[Integer] {
    type To = String
    def to(value: Integer) = ???
  }
}

// this works
val single = the[Converter[Integer]]
implicitly[single.To =:= String]
val singleAux = the[Converter.Aux[Integer, String]]

HLists で動作するようにしたいと思いInteger :: HNilます。理論的には、必要なのは HNil と HList の暗黙的なものだけです。

implicit val forHNil = new Converter[HNil] {
  type To = HNil
  def to(value: HNil) = HNil
}

implicit def forHList[Head, HeadConverted, Tail <: HList, TailConverted <: HList](
  implicit
  hConverter: Converter.Aux[Head, HeadConverted],
  tConverter: Converter.Aux[Tail, TailConverted]
  ): Converter[Head :: Tail] = new Converter[Head :: Tail] {
    type To = HeadConverted :: TailConvertedHList
    def to(values: Head :: Tail) = ???
  }

上記は HNil に対して正常に機能します。

val hnil = the[Converter[HNil]]
implicitly[hnil.To =:= HNil]
val hnilAux = the[Converter.Aux[HNil, HNil]]

しかし、HList ではありません。興味深いことに、インスタンスは見つかりますが、結果の型は派生しません。

val hlist = the[Converter[Integer :: HNil]]
type expected = String :: HNil
implicitly[hlist.To =:= expected] //fails
val hlistAux = the[Converter.Aux[Integer :: HNil, String :: HNil]] // fails

問題をデバッグするためにさらにいくつかの(失敗した)試みがある自己完結型のプロジェクトでそれを設定しました:https://github.com/mpollmeier/shapeless-dependent-type-typeclass-problem

4

1 に答える 1

1

forHList問題は、 asの戻り値の型を明示的に述べたことConverter[Head :: Tail]です。その戻り値の型は不完全で、必要な部分が正確に欠落しています。

宣言された戻り値の型を変更するConverter.Aux[Head :: Tail, HeadConverted :: TailConverted]だけで (または省略しても)、問題は解決します。

この回答の功績はすべて Miles Sabin にあり、彼は上記のコメントで問題について言及しました。ありがとうございました!

于 2017-05-02T22:08:40.610 に答える