3

HList簡単にするために、インスタンスが正確に 2 つの値を保持していると仮定します。

def intToString(x: Int) = x + "_"
def intToDouble(x: Int) = x * 10d
val fns = (intToString _ :: intToDouble _ :: HNil)

今、私はいくつかHlistのintを持って、これを行うことができるようにしたいと思います:

(fns zip (1 :: 2 :: HList) map {case (f, x) => f(x) }

取得するため

("1_", 10.0)

これからは、自分が何をしているのかわからないと仮定し、関数の神々の前で自分の卑劣さを完全に理解している.

私はすでに shapeless の wiki を見てきましたが、私が理解している限りでは、shapeless で受け入れられるInttoから関数を作成する必要があります。T私は正しく理解しましたか?これが私が得たものです:

object mapApply extends Poly1 {
  implicit def default[T] = at[Function[Int,T]](f => f.apply _)
}

この時点で、私は完全に道に迷っており、先に進む方法さえわかりません。でも、これがもたらす潜在的な力と表現力にちょっと魅了されているので、この機能がどのように機能するかを本当に理解したいと思っています. あなたの答えが単なるコードスニペットではなく、よりオープンで説明的なものになることを本当に感謝しています.

c++PS SO のエンジンがタグを提案してくれました。私は何か C++ っぽいことを言いましたか?

4

1 に答える 1

3

メソッドと関数の定義構文が混在しているようです。次のような意味だと思います。

val intToString = (x: Int) => x + "_"
val intToDouble = (x: Int) => x * 10d
val fns = intToString :: intToDouble :: HNil

zipApplyこれで、関数とその引数をペアにするだけで使用できます。

val res = fns.zipApply(1 :: 2 :: HNil)

何らかの理由zipApplyで存在しない場合は、次のようにして同じことを達成できますPoly1

object apply extends Poly1 {
  implicit def default[I, O]: Case.Aux[(I => O, I), O] =
    at[(I => O, I)] { case (f, x) => f(x) }
}

val res = fns.zip(1 :: 2 :: HNil).map(apply)

または、余分な汎用性が必要ない場合は、次のようにします。

object applyToInt extends Poly1 {
  implicit def default[T]: Case.Aux[(Int => T, Int), T] =
    at[(Int => T, Int)] { case (f, x) => f(x) }
}

したがって、あなたはそう遠くはありませんでした —関数だけでなく、関数と引数Poly1ペアのケースが必要だっただけです。

于 2014-07-10T20:57:59.267 に答える