ScalaがFunction1とFunction2..Nを処理する際に明らかな矛盾がある場合にパッチを当てる方法があるかどうかは疑問です。 Function1
についてScalaの型システムとFunctionNへの入力
は、Int => String
を言う、パラメータリスト(INT)が(二つの同型であっても)がINTと同一ではない、まだコンパイラは裸INT(以下のコードを参照)として入力を推測します。
Function2..N
の場合、 val f:(String、Int)=> String = ??? コンパイラは入力パラメータリストの型を推論しません。特に、(String、Int)のタプルおよびStringsとIntsを置くことを好む他のラッパーと同形であっても、ParameterList [String、Int]はありません。
私の最初の質問は、これがこのような理由があるかどうかです(またはこれはスカラートードのリストに存在します)。すなわち、なぜFunction1を入出力タイプに分解することができますが、Function2は分解することができず、それを修正したいのですか?
回避策はありますか?特に、以下のコードでは、invoke2を動作させる方法はありますか?
package net.jtownson.swakka
import org.scalatest.FlatSpec
import org.scalatest.Matchers._
import shapeless.ops.function._
import shapeless.{HList, HNil, _}
class TypeclassOfFunctionTypeSpec extends FlatSpec {
// Here, we know the return type of F is constrained to be O
// (because that's how the shapeless FnToProduct typeclass works)
def invoke1[F, I <: HList, O](f: F, i: I)
(implicit ftp: FnToProduct.Aux[F, I => O]): O = ftp(f)(i)
// So let's try to express that by extracting the input type of F as FI
def invoke2[FI, I <: HList, O](f: FI => O, i: I)
(implicit ftp: FnToProduct.Aux[FI => O, I => O]): O = ftp(f)(i)
"Invoke" should "work for a Function1" in {
// Here's our function (Int) => String
val f: (Int) => String = (i) => s"I got $i"
val l = 1 :: HNil
// this works
val r1: String = invoke1(f, l)
// So does this. (With evidence that the compiler sees the function parameter list (Int) as just Int
val r2: String = invoke2[Int, Int::HNil, String](f, l)
r1 shouldBe "I got 1"
r2 shouldBe "I got 1"
}
"Invoke" should "work for a Function2" in {
// Here's our function (String, Int) => String
val f: (String, Int) => String = (s, i) => s"I got $s and $i"
val l = "s" :: 1 :: HNil
// this works
val r1: String = invoke1(f, l)
// But this does not compile. There is no expansion for the type of FI
// (String, Int) != the function Parameter list (String, Int)
val r2: String = invoke2(f, l)
/*
Error:(...) type mismatch;
found : (String, Int) => String
required: ? => String
val r1: String = invoke1(f, l)
*/
r1 shouldBe "I got s and 1"
r2 shouldBe "I got s and 1"
}
}
で
invoke2
を呼び出すことができFnToProduct
インスタンスを解決するための型崩れを助けることができますが、 '機能2番号のtupled'と'機能2番号を認識していますカレーの方法? –はい、私は:-)です。また、関数1にはタプルが存在しません。おそらくこれは、Function1の_input_(裸のタイプ)のタイプを表現する能力は、タプルが必要でないことを意味するからです。悪い古いFunction2..Nこれは欠けている。この意味で、タプルは回避策のように感じます。私は何を疑問に思いますか?この点については、Function1とFunction2の間に相違がある理由はありますか? –