다음을 통해 공유


제네릭

F# 함수 값, 메서드, 속성 및 클래스, 레코드 및 구분된 공용 구조체와 같은 집계 형식은 제네릭일 수 있습니다. 제네릭 구문에는 일반적으로 제네릭 구문 사용자가 제공하는 하나 이상의 형식 매개 변수가 포함됩니다. 제네릭 함수 및 형식을 사용하면 각 형식에 대한 코드를 반복하지 않고도 다양한 형식으로 작동하는 코드를 작성할 수 있습니다. 코드는 컴파일러의 형식 유추 및 자동 일반화 메커니즘에 의해 암시적으로 제네릭으로 유추되기 때문에 F#에서 코드를 제네릭으로 만드는 것이 간단할 수 있습니다.

문법

// Explicitly generic function.
let function-name<type-parameters> parameter-list =
function-body

// Explicitly generic method.
[ static ] member object-identifier.method-name<type-parameters> parameter-list [ return-type ] =
method-body

// Explicitly generic class, record, interface, structure,
// or discriminated union.
type type-name<type-parameters> type-definition

비고

명시적으로 제네릭 함수 또는 형식의 선언은 함수 또는 형식 이름 뒤의 꺾쇠 괄호 안에 있는 형식 매개 변수의 사양(및 사용)을 제외하고 제네릭이 아닌 함수 또는 형식의 선언과 비슷합니다.

선언은 종종 암시적으로 제네릭입니다. 함수 또는 형식을 작성하는 데 사용되는 모든 매개 변수의 형식을 완전히 지정하지 않으면 컴파일러는 작성하는 코드에서 각 매개 변수, 값 및 변수의 형식을 유추하려고 시도합니다. 자세한 내용은 형식 유추를 참조하세요. 형식 또는 함수에 대한 코드가 매개 변수 형식을 제한하지 않는 경우 함수 또는 형식은 암시적으로 제네릭입니다. 이 프로세스의 이름은 자동 일반화입니다. 자동 일반화에는 몇 가지 제한이 있습니다. 예를 들어 F# 컴파일러가 제네릭 구문의 형식을 유추할 수 없는 경우 컴파일러는 값 제한이라는 제한을 참조하는 오류를 보고합니다. 이 경우 일부 형식 주석을 추가해야 할 수 있습니다. 자동 일반화 및 값 제한 및 문제를 해결하기 위해 코드를 변경하는 방법에 대한 자세한 내용은 자동 일반화를 참조하세요.

이전 구문에서 형식 매개 변수 는 알 수 없는 형식을 나타내는 쉼표로 구분된 매개 변수 목록이며, 각 매개 변수는 필요에 따라 해당 형식 매개 변수에 사용할 수 있는 형식을 추가로 제한하는 제약 조건 절을 사용하여 작은따옴표로 시작합니다. 다양한 종류의 제약 조건 절에 대한 구문 및 제약 조건에 대한 기타 정보는 제약 조건을 참조하세요.

구문의 형식 정의 는 제네릭이 아닌 형식에 대한 형식 정의와 동일합니다. 클래스 형식에 대한 생성자 매개 변수, 선택적 as 절, 등호, 레코드 필드, 절, inherit 구분된 공용 구조체에 대한 선택 사항, letdo 바인딩, 멤버 정의 및 제네릭이 아닌 형식 정의에서 허용되는 기타 항목이 포함됩니다.

다른 구문 요소는 제네릭이 아닌 함수 및 형식의 구문 요소와 동일합니다. 예를 들어 개체 식별자는 포함하는 개체 자체를 나타내는 식별자입니다.

속성, 필드 및 생성자는 바깥쪽 형식보다 제네릭일 수 없습니다. 또한 모듈의 값은 제네릭일 수 없습니다.

암시적으로 제네릭 구문

F# 컴파일러가 코드의 형식을 유추하면 제네릭일 수 있는 모든 함수를 제네릭으로 자동으로 처리합니다. 매개 변수 형식과 같이 형식을 명시적으로 지정하면 자동 일반화를 방지할 수 있습니다.

다음 코드 예제 makeList 에서는 제네릭 또는 해당 매개 변수가 제네릭으로 명시적으로 선언되지 않더라도 제네릭입니다.

let makeList a b = [ a; b ]

함수의 시그니처는 .로 유추됩니다 'a -> 'a -> 'a list. a b 이 예제에서는 동일한 형식을 갖도록 유추됩니다. 이는 목록에 함께 포함되고 목록의 모든 요소가 동일한 형식이어야 하기 때문입니다.

매개 변수 형식이 제네릭 형식 매개 변수임을 나타내기 위해 형식 주석의 작은따옴표 구문을 사용하여 함수 제네릭을 만들 수도 있습니다. 다음 코드 function1 에서는 해당 매개 변수가 형식 매개 변수로 이러한 방식으로 선언되기 때문에 제네릭입니다.

let function1 (x: 'a) (y: 'a) = printfn "%A %A" x y

명시적으로 제네릭 구문

또한 형식 매개 변수를 꺾쇠 괄호(<type-parameter>)로 명시적으로 선언하여 함수 제네릭을 만들 수도 있습니다. 다음 코드에서는 이를 보여 줍니다.

let function2<'T> (x: 'T) (y: 'T) = printfn "%A, %A" x y

제네릭 구문 사용

제네릭 함수 또는 메서드를 사용하는 경우 형식 인수를 지정할 필요가 없습니다. 컴파일러는 형식 유추를 사용하여 적절한 형식 인수를 유추합니다. 여전히 모호성이 있는 경우 여러 형식 인수를 쉼표로 구분하여 꺾쇠 괄호 안에 형식 인수를 제공할 수 있습니다.

다음 코드는 이전 섹션에서 정의한 함수의 사용을 보여 줍니다.

// In this case, the type argument is inferred to be int.
function1 10 20
// In this case, the type argument is float.
function1 10.0 20.0
// Type arguments can be specified, but should only be specified
// if the type parameters are declared explicitly. If specified,
// they have an effect on type inference, so in this example,
// a and b are inferred to have type int.
let function3 a b =
    // The compiler reports a warning:
    function1<int> a b
    // No warning.
    function2<int> a b

비고

이름으로 제네릭 형식을 참조하는 방법에는 두 가지가 있습니다. 예를 들어 list<int>int list 단일 형식 인수int가 있는 제네릭 형식 list 을 참조하는 두 가지 방법이 있습니다. 후자의 양식은 일반적으로 기본 제공 F# 형식(예: listoption.)에서만 사용됩니다. 여러 형식 인수가 있는 경우 일반적으로 구문을 Dictionary<int, string> 사용하지만 구문을 (int, string) Dictionary사용할 수도 있습니다.

형식 인수로서의 와일드카드

컴파일러에서 형식 인수를 유추하도록 지정하려면 명명된 형식 인수 대신 밑줄 또는 와일드카드 기호()_를 사용할 수 있습니다. 다음 코드에 이러한 내용이 나와 있습니다.

let printSequence (sequence1: Collections.seq<_>) =
    Seq.iter (fun elem -> printf "%s " (elem.ToString())) sequence1

제네릭 형식 및 함수의 제약 조건

제네릭 형식 또는 함수 정의에서는 제네릭 형식 매개 변수에서 사용할 수 있는 것으로 알려진 구문만 사용할 수 있습니다. 컴파일 시간에 함수 및 메서드 호출을 확인하는 데 필요합니다. 형식 매개 변수를 명시적으로 선언하는 경우 제네릭 형식 매개 변수에 명시적 제약 조건을 적용하여 컴파일러에 특정 메서드와 함수를 사용할 수 있음을 알릴 수 있습니다. 그러나 F# 컴파일러가 제네릭 매개 변수 형식을 유추하도록 허용하면 적절한 제약 조건이 결정됩니다. 자세한 내용은 제약 조건을 참조하세요.

정적으로 확인된 형식 매개 변수

F# 프로그램에서 사용할 수 있는 형식 매개 변수에는 두 가지 종류가 있습니다. 첫 번째는 이전 섹션에서 설명한 종류의 제네릭 형식 매개 변수입니다. 이 첫 번째 종류의 형식 매개 변수는 Visual Basic 및 C#과 같은 언어에서 사용되는 제네릭 형식 매개 변수와 동일합니다. 다른 종류의 형식 매개 변수는 F#과 관련이 있으며 정적으로 확인된 형식 매개 변수라고 합니다. 이러한 구문에 대한 자세한 내용은 정적으로 확인된 형식 매개 변수를 참조하세요.

예시

// A generic function.
// In this example, the generic type parameter 'a makes function3 generic.
let function3 (x: 'a) (y: 'a) = printf "%A %A" x y

// A generic record, with the type parameter in angle brackets.
type GR<'a> = { Field1: 'a; Field2: 'a }

// A generic class.
type C<'a>(a: 'a, b: 'a) =
    let z = a
    let y = b
    member this.GenericMethod(x: 'a) = printfn "%A %A %A" x y z

// A generic discriminated union.
type U<'a> =
    | Choice1 of 'a
    | Choice2 of 'a * 'a

type Test() =
    // A generic member
    member this.Function1<'a>(x, y) = printfn "%A, %A" x y

    // A generic abstract method.
    abstract abstractMethod<'a, 'b> : 'a * 'b -> unit
    override this.abstractMethod<'a, 'b>(x: 'a, y: 'b) = printfn "%A, %A" x y

참고하십시오