トリック推論を入力するためには、反復改良のプロセスとしてそれを考えることです。各パラメータブロックを使用して、タイプパラメータの一部を推論することができ、後続のブロックで使用することができます。だから、次の定義を行いますと呼ばれる
def chain[T,A,B](x: T)(fn1: T=>A)(fn2: A=>B) = fn2(fn1(x))
:
chain(2)(_*10)("xxx"+_)
は、どのようにこれは推測されているのですか?まず、タイプInt
であることが知られているブロック(2)
から始めます。
def chain[A,B](x: Int)(fn1: Int=>A)(fn2: A=>B) = fn2(fn1(x))
次のパラメータブロックは、我々は今Int
するプレースホルダ_
の種類を知っているところ、(_*10)
です...とInt
でInt
を掛けることは、別のInt
を与える:その背中我々が得るT
パラメータへの代入。これはオーバーフローが発生しても返される型に当てはまります。極端な場合、例外がスローされる可能性がありますが、例外は型システムの他のすべてのサブクラスであるタイプNothing
を持っています。したがってNothing
は-Int
であり、推測型はInt
です。推論A
で
、方法は次のようになる。
def chain[B](x: Int)(fn1: Int=>Int)(fn2: Int=>B) = fn2(fn1(x))
のみB
("xxx"+_)
から推測することができるが残ります。String + Int
がString
であるように、この方法は、以下のようになります。また、明示的に完全を期すために示すことができるメソッドの戻り値の型fn2
から直接来て、として
def chain(x: Int)(fn1: Int=>Int)(fn2: Int=>String) = fn2(fn1(x))
:
あり
def chain(x: Int)(fn1: Int=>Int)(fn2: Int=>String): String = fn2(fn1(x))
あなたはそれを持っていますすべての型が安全に解決され、メソッドが静的に有効であることが証明されています。あなたのケースでは
、あなたはそれがタイプT=>R
からR
を推測することが可能です前に推論されるタイプT
を必要としています。これを行うには、パラメータを2つの別個のブロックに分割し、カレー形式でメソッドを記述する必要があります。
def callOn[T,R](target: T)(f: (T => R)) = f(target)
ありがとうございました。この単純なケースがあるとしましょう: 'def callOn4 [R](f:(Int => R))= f(4)'。なぜ私は 'def callOn4(f:(Int => _))= f(4)'と定義すればいいのですか? –
@jpp - ちょっと試してみて、あなたの2番目のバージョンでどのような戻り値の型が推測されるのか... –