2016-09-02 21 views
0

スカラー型パラメーターの概念を理解しようとしています。スカラー型パラメーター

def sum [A] (a:A):A={a} 
// used single parameter and its working fine, able to pass any data type. 

ここ:

def sum[A](a:A,b:A):A={a+b} //declare two arguments 

<console>:7: error: type mismatch; 
found : A 
required: String 
def sum[A](a:A,b:A):A={a+b} 

上記の関数は、型パラメータを持って、私は、任意のデータ型を言及していない - それは文字列として扱われますどのように来ますか?

答えて

3
def sum[A](a:A,b:A):A={a+b} 

あなたはT+Tを追加している、コンパイラがTため+を推測することはできません、それはデフォルトimplicit +使用します。any2stringaddをするので、コンパイラがrequired: Stringエラーがスローされます。

https://issues.scala-lang.org/browse/SI-8229

implicit final class any2stringadd[A](private val self: A) extends AnyVal { 
    def +(other: String): String = String.valueOf(self) + other 
    } 
2

はのは少し違った視点からこのを見てみましょう参照してください、実際には、パラメータは何ですか?どういう意味ですか?

まず、よく知っているものから始めましょう:値のパラメータ。サブルーチンの値パラメータはどういう意味ですか?それは意味

def foo(a, b) = { /* … */ } // deliberately ignoring types and the body 

::私は2つのパラメータ、abでサブルーチンfooを持って、我々はこのような何かを持っている、と言います。そして、サブルーチンは一般です、の実際の具体的な値はabです。 すべての値がabの場合は、がありません。の値はabの値であるためです。

もう少し具体的な:

def plus(a: Int, b: Int) = a + b 

ここでも、plusabの実際の値が何であるかを知りません。 23だけでなく、2342または00の場合も同様です。 abの具体的な値は完全に完全に知られていません。 abが存在することだけがわかります。

ここで、タイプのパラメータは、値レベルではなくタイプレベルでのみ同じです。 「私はものを持って、私はそれが何であるか見当がつかない(と私は気にしない)が、私は電話するよ:

blabla[A] 

blabla(a)が値レベルでの手段として、タイプレベルで同じことを意味し、それはAです。

あなたが効果的に行ったことは、Aについて何も知らないことをScalaに伝えることです。しかし、あなたはそれを使って(あるいはそのインスタンスを使って)何かを行います:それを追加します。しかし、どのようにあなたもあなたを知っていますそれを追加しますか?あなたはそれが何であるかを知りません!

ので、はおそらく動作しないすることができ、それを追加し、それが失敗しなければなりません!

ただし、の方法はです。これは、少し不思議で、scala.Predefオブジェクトの定義済みの暗黙的な変換のいくつかと関係があります。特に、there is an implicit conversion for string concatenation, which can convert an arbitrary object into a String and then concatenate another String to it。この場合、aany2stringaddに変換してからbを追加しようとしますが、メソッドはStringを引数にとり、Stringが必要であるという奇妙なエラーメッセージが表示されます。あなたは、複雑な型エラーがある場合

は、時々ポップアップ表示の他の同様のタイプのカップルがあります。

  • AnyAnyRefAnyVal:これらのタイプは、Scalaの型階層の最上部に座っています。ときどき、2つの異なるコードパスから同じ型を返すと思われるプログラミングエラーがありますが、実際には2つの異なる型を返す場合、Scalaはそれにもかかわらず両方の共通型を推測しようとします。共通祖先はAny,AnyRefまたはAnyValです。 (これはJavaやC#でObjectのようなものです)
  • Serializable:これは実際には上記と同じです。完全に異なる型の多くはSerializableインターフェイスを実装しているので、実際に同じ型を期待する2つの型が非常に異なる場合、ScalaはSerializableを最も近い共通の祖先として推測し、Serializableそれはサポートしていません。
  • Productは(Tuple22すなわちTuple1Tuple2、...)(...、即ちProduct1Product2Product22)全てProduct Sのスーパー形質であり、従って全てTuple S。 Productもすべてcase classに混在しています。 Optionとあなたのcase class FooProductかと推測される間、その後、最も正確な一般的なタイプを使用すると、異なるアリティの2 Tuple秒または2個の無関係なcase class ESを持っているのであれば、(例えば、あなたは時々Noneを返すが、その後偶然代わりSome(somethingOfTypeFoo)somethingOfTypeFooを返します)...
  • Product with Serializable:上記の組み合わせを受け取ることもできます。例えば。 TupleSerializableであるので、このは実際には異なるアリティの2つの最も正確な一般的なタイプです。これらの問題に実行する

一般的な方法の1つは、elseなしの条件式である:

if (true) 42 

このリターンを何種類? Int?いいえ! thenブランチはIntを返しますが、elseブランチはを返しません。elseブランチがないため)。スカラは実際に何も返さない戻り値の型を持っています:UnitUnitAnyValのサブタイプであり、IntAnyValのサブタイプであるため、条件式の2つのブランチのタイプのうち最も近い共通祖先は、ではありません。Intではありません。 (注:elseブランチが到達不能であるという事実は、入力の観点からは無関係です。到達可能性は実行時のものです。タイプはコンパイル時のものです)

関連する問題