2017-08-06 6 views
0

私はカスタムタイプ、Valueあります内蔵タイプ

sealed trait GetsValue[T] { def apply(record: T): Option[Value] } 
object GetsValue { 
    trait GetsBooleanValue[T] extends GetsValue[T] { override def apply(record: T): Option[Value.BooleanValue] } 
    trait GetsLongValue[T] extends GetsValue[T] { override def apply(record: T): Option[Value.LongValue] } 
} 

trait Value 
object Value { 
    case class BooleanValue(record: Boolean) extends Value 
    case class LongValue(record: Long) extends Value 
} 

そしてValueを取得する方法を知っている特性は、いくつかの入力タイプTを与え、GetsValueと呼ばれます

GetsValueは封印されているため、ユーザーはGetsValue.GetsBooleanValueまたはGetsValue.GetsLongValueにしか拡張されません。

trait Extractor[T] { 
    def title: String 
    def getsValue: GetsValue[T] 
    def relatedValue[U]: U = ??? // question below 
} 

私は何を達成したいことは以下の通りです: "!BOO"

getsValueGetsValue.GetsBooleanValue[_]であれば、テキストでStringを返します(すなわちUはタイプStringです)。

getsValue場合は、その後(すなわち、UタイプDoubleである)1.1の値でDoubleを返す、GetsValue.GetsLongValue[_]あります。

getsValueのタイプTとは一致しません。私はそのタイプTとは無関係にマッチしたいです。

意味が分かれば、タイプクラス/インプリシットを使用したいと思います。 Eitherを使用することは私の選択肢ではありません。

+0

私はそれがうまくいくとは思わないが、パスに依存する型を使用しても、ラップされたdouble/Stringを持つことができます。 –

答えて

2

おそらくこのような何かが働くだろう:

まず、戻り値の型を指定する、タイプパラメータを追加するGetsValueを変更します。

sealed trait GetsValue[T, V <: Value] { def apply(record: T): Option[V] } 
object GetsValue { 
    trait GetsBooleanValue[T] extends GetsValue[T, Value.BooleanValue] { } 
    trait GetsLongValue[T] extends GetsValue[T, Value.LongValue] { } 
} 

その後の値にタイプVを相関させる特性U

trait RelatedValue[V <: Value, U] { 
    def get: U 
} 

そして、その形質のいくつかの暗黙の値:

object Extractor { 
    implicit val boolRV = new RelatedValue[Value.BooleanValue, String] { def get = "boo!" } 
    implicit val longRV = new RelatedValue[Value.LongValue, Double] { def get = 1.1 } 
} 

その後、あなたのExtractorの特性を指定できます

trait Extractor[T] { 
    type V <: Value 
    type U 
    def title: String 
    def getsValue: GetsValue[T, V] 
    def relatedValue(implicit rv: RelatedValue[V, U]): U = rv.get 
} 

実装例: "!BOO"

object Example extends Extractor[String] { 
    type V = Value.BooleanValue 
    type U = String 
    def title = "Example" 
    def getsValue = new GetsValue.GetsBooleanValue[String] { 
    def apply(s: String) = None 
    } 
} 

import Extractor._ 
println(Example.relatedValue) 

プリント

関連する問題