型推論Type Inference

このトピックでは、F# コンパイラが値、変数、パラメーター、戻り値の型を推定する方法について説明します。This topic describes how the F# compiler infers the types of values, variables, parameters and return values.

型の推定一般Type Inference in General

型の推定の概念は、コンパイラが最終的に型を推測できない場合を除いて、F# コンストラクトの型を指定する必要がないということです。The idea of type inference is that you do not have to specify the types of F# constructs except when the compiler cannot conclusively deduce the type. 明示的な型情報を省略するのは、F# が動的型付け言語であるという意味でも、その F# の値の型付けが弱いという意味でもありません。Omitting explicit type information does not mean that F# is a dynamically typed language or that values in F# are weakly typed. F# は、静的型付け言語です。つまり、コンパイラはコンパイル時に各コンストラクトに対して正確な型を推測します。F# is a statically typed language, which means that the compiler deduces an exact type for each construct during compilation. コンパイラが各コンストラクトの型を推測するのに十分な情報がない場合は、通常、コード内のどこかに明示的な型の注釈を追加することにより、追加の型情報を指定する必要があります。If there is not enough information for the compiler to deduce the types of each construct, you must supply additional type information, typically by adding explicit type annotations somewhere in the code.

パラメーターと戻り値の型の推定Inference of Parameter and Return Types

パラメーター リストでは、各パラメーターの型を指定する必要はありません。In a parameter list, you do not have to specify the type of each parameter. それでも、F# は静的型付け言語であるため、すべての値と式にはコンパイル時に明確な型が指定されます。And yet, F# is a statically typed language, and therefore every value and expression has a definite type at compile time. 明示的に指定しない型については、コンパイラがコンテキストに基づいて型を推定します。For those types that you do not specify explicitly, the compiler infers the type based on the context. 型が指定されていない場合は、ジェネリックであると推定されます。If the type is not otherwise specified, it is inferred to be generic. コード内で、ある値が一貫性のある方法で使用されていない場合 (ある値のすべての使用箇所で条件にかなう単一の推定型がない場合など)、コンパイラによりエラーが報告されます。If the code uses a value inconsistently, in such a way that there is no single inferred type that satisfies all the uses of a value, the compiler reports an error.

関数の戻り値の型は、関数に含まれている最後の式の型によって決まります。The return type of a function is determined by the type of the last expression in the function.

たとえば、次のコードでは、リテラル 100 の型が int であるため、パラメーターの型 ab、および戻り値の型はすべて int と推定されます。For example, in the following code, the parameter types a and b and the return type are all inferred to be int because the literal 100 is of type int.

let f a b = a + b + 100

リテラルを変更することで、型の推定に影響を与えることができます。You can influence type inference by changing the literals. サフィックス u を追加して 100uint32 にする場合、ab、戻り値の型は uint32 と推定されます。If you make the 100 a uint32 by appending the suffix u, the types of a, b, and the return value are inferred to be uint32.

特定の型のみを処理する関数やメソッドなど、型に制限がある他の構造体を使用して、型の推定に影響を与えることもできます。You can also influence type inference by using other constructs that imply restrictions on the type, such as functions and methods that work with only a particular type.

また、次の例に示すように、関数やメソッドのパラメーターまたは式の変数に明示的な型の注釈を適用することもできます。Also, you can apply explicit type annotations to function or method parameters or to variables in expressions, as shown in the following examples. 異なる制約の間で競合が発生すると、エラーが発生します。Errors result if conflicts occur between different constraints.

// Type annotations on a parameter.
let addu1 (x : uint32) y =
    x + y

// Type annotations on an expression.
let addu2 x y =
    (x : uint32) + y

また、すべてのパラメーターの後に型の注釈を指定して、関数の戻り値を明示的に指定することもできます。You can also explicitly specify the return value of a function by providing a type annotation after all the parameters.

let addu1 x y : uint32 =
   x + y

パラメーターで型の注釈が役立つ一般的なケースは、パラメーターがオブジェクト型で、メンバーを使用する場合です。A common case where a type annotation is useful on a parameter is when the parameter is an object type and you want to use a member.

let replace(str: string) =
    str.Replace("A", "a")

自動ジェネリック化Automatic Generalization

関数コードがパラメーターの型に依存していない場合、コンパイラはパラメーターをジェネリックと見なします。If the function code is not dependent on the type of a parameter, the compiler considers the parameter to be generic. これは "自動ジェネリック化" と呼ばれ、複雑さを増大させることなくジェネリック コードを記述するための強力な機能となります。This is called automatic generalization, and it can be a powerful aid to writing generic code without increasing complexity.

たとえば、次の関数は、任意の型の 2 つのパラメーターを結合してタプルにします。For example, the following function combines two parameters of any type into a tuple.

let makeTuple a b = (a, b)

型は、次のように推定されます。The type is inferred to be

'a -> 'b -> 'a * 'b

追加情報Additional Information

型の推定については、F# 言語仕様でさらに詳しく説明されています。Type inference is described in more detail in the F# Language Specification.

関連項目See also