私がこのような型クラスを持っているとしましょう:
trait Select[A] {
def select(selector: String): Set[A]
}
タイプクラスは、「セレクター文字列が与えられた場合、A
オブジェクトのセットを提供する」機能を提供します。ただし、これを複数回行う必要がある場合は、すぐに疲れます。
val setOfGrapes = Select[Grape].select("red-seedless")
val setOfApples = Select[Apple].select("fuji-apple")
// and so on...
私のプログラムでは、ユーザーが複数のセレクターを含む文字列を入力できるため、これはすべて実行時に行われます。
これをより簡潔にするために、このように使用できる関数を作成するためにシェイプレスを使用するにはどうすればよいですか?
val setOfGrapes :: setOfApples :: HNil =
selectMultiple("red-seedless, fuji")(Select[Grape] :: Select[Apple] :: HNil)
動機は、複数Select
のをすばやく連鎖させることができることです。本質的に、私はからメソッドを実行するSelect[Grape] :: Select[Apple] :: HNil
ことSet[Grape] :: Set[Apple] :: HNil
によってに行きSelect
ます。
文字列処理(コンマ、グロブなどの処理)を無視して、これを実装するにはどうすればよいですか?
私はこれを試しました:
object fun extends Poly1 {
implicit def selectCase[A] = at[Select[A]](_.select(""))
}
def mapFun[H <: HList](inputs: H) = inputs map fun
コンパイラは私に、を教えてくれcould not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[fun.type,H]
ます。これは、HListのすべての要素がであるとは保証できないためだと思いSelect[A]
ます。コンパイラにこれを伝えるにはどうすればよいですか?
私はshapeless.UnaryTCConstraint[H, Select]
このように指定しようとしました:
def mapFun[H <: HList](inputs: H)(implicit ev: shapeless.UnaryTCConstraint[H, Select]) = inputs map fun
しかし、同じエラーが発生します。
友人が私の使用をお勧めしますComapped
、Mapper
と~>
私はこれを試してみましたので、:
object mapper extends (Select ~> Set) {
override def apply[A](s: Select[A]): Set[A] = s.select(???)
}
def mapFun[II <: HList, OO <: HList](inputs: II)(
implicit ev: Comapped.Aux[II, Select, OO],
ev2: Mapper.Aux[mapper.type, II, OO]
): OO = input map fun
しかし、コンパイラcould not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[ammonite.$sess.cmd8.fun.type,II]
。
基本的に、必要な暗黙の証拠をmapFun
メソッドに追加するだけです。
object fun extends Poly1 {
implicit def selectCase[A] = at[Select[A]](_.select(""))
}
def mapFun[H <: HList](inputs: H)(implicit m: Mapper[fun.type, H]) = inputs map fun
scala> mapFun(Select[Apple] :: Select[Grape] :: Select[Apple] :: HNil)
val res1: scala.collection.immutable.Set[Apple] :: scala.collection.immutable.Set[Grape] :: scala.collection.immutable.Set[Apple] :: shapeless.HNil = Set(Apple@44ebbbe8) :: Set(Grape@76eae32c) :: Set(Apple@666f67b6) :: HNil
好みのAPIを取得するには、次のような「手動カリー化」関数を導入できます。
class SelectMultipleApply(selector: String) {
def apply[H <: HList](inputs: H)(implicit m: Mapper[fun.type, H]) = inputs map fun
object fun extends Poly1 {
implicit def selectCase[A] = at[Select[A]](_.select(selector))
}
}
def selectMultiple(selector: String) = new SelectMultipleApply(selector)
scala> selectMultiple("red-seedless, fuji")(Select[Grape] :: Select[Apple] :: HNil)
val res5: scala.collection.immutable.Set[Grape] :: scala.collection.immutable.Set[Apple] :: shapeless.HNil = Set(Grape@63c81efa) :: Set(Apple@29dbae38) :: HNil
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加