Udostępnij za pośrednictwem


Automatyczna generalizacja (F#)

F# używa typu wnioskowanie do oceny typy funkcji i wyrażeń.W tym temacie opisano, jak F# automatycznie uogólnia argumentów i typy funkcji, aby mogły działać z wielu typów, gdy jest to możliwe.

Automatyczne generalizacji

F# kompilator, gdy wykonuje typu wnioskowanie o funkcji, określa, czy dany parametr może być rodzajowy.Kompilator bada każdego parametru i określa, czy funkcja ma zależności na określony typ parametru.Jeśli nie, typ jest niezamierzone być rodzajowy.

Poniższy przykład kodu ilustruje funkcji, która być rodzajowy jest ustalany przez kompilator.

let max a b = if a > b then a else b

Typ jest niezamierzone za 'a -> 'a -> 'a.

Typ wskazuje, że jest to funkcja, która ma dwa argumenty tej samej nieznany typ i zwraca wartość z tego samego typu.Jednym z powodów, dla których funkcja poprzednich może być rodzajowy jest większa-niż operator (>) jest rodzajowy.Większa-niż operator ma podpis 'a -> 'a -> bool.Nie wszystkie podmioty gospodarcze mają charakter ogólny, i jeśli kod w funkcji używa typu parametru wraz z funkcją nierodzajową lub operator, typ tego parametru nie uogólnione.

Ponieważ max jest rodzajowy, go może być używany z typami takie jak int, float, i tak dalej, jak pokazano w poniższych przykładach.

let biggestFloat = max 2.0 3.0
let biggestInt = max 2 3

Jednakże dwa argumenty muszą być tego samego typu.Podpis jest 'a -> 'a -> 'a, nie 'a -> 'b -> 'a.W związku z tym poniższy kod generuje błąd, ponieważ typy nie pasują do siebie.

// Error: type mismatch.
let biggestIntFloat = max 2.0 3

max Funkcji współpracuje również z dowolnego typu, który obsługuje większa-niż operator.W związku z tym można także użyć go na ciąg, jak pokazano w poniższym kodzie.

let testString = max "cab" "cat"

Wartość ograniczenia

Kompilator wykonuje generalizacji automatyczne tylko w definicji funkcji kompletne, które mają wyraźne argumenty i wartościami niezmiennymi proste.

Oznacza to, kompilator generuje błąd, jeśli skompilować kod, który nie jest wystarczająco ograniczony do określonego typu, ale nie jest również generalizacji.Komunikat o błędzie dla tego problemu odnosi się do tego ograniczenia na automatyczne generalizację dla wartości jako ograniczenie wartości.

Zazwyczaj wartość Błąd ograniczenia występuje podczas ma konstrukcja być rodzajowy, ale kompilator ma niewystarczające informacje do upowszechnienia go, albo nieumyślnie pominięty wystarczające informacje o typie w nierodzajowe konstrukcji.Rozwiązanie błędu ograniczenie wartości jest uzyskać dokładniejsze informacje bardziej pełni ograniczyć typ problemu wnioskowanie, w jednym z następujących sposobów:

  • Ograniczyć typ, który ma być nierodzajowe przez dodanie adnotacji jawnie określony typ wartości lub parametr.

  • Jeśli ten problem przy użyciu konstrukcji nongeneralizable do definiowania rodzajowy funkcji, takich jak skład funkcji lub nie w pełni stosowane argumenty funkcji curried, spróbuj ponownie napisać funkcję jak definicję zwykłej funkcji.

  • Jeśli problem jest wyrażenie jest zbyt skomplikowane, aby być uogólnione, Przekształć go w funkcji przez dodanie parametru ekstra, nieużywane.

  • Dodaj parametry wyraźnej typu rodzajowego.Ta opcja jest rzadko używana.

  • Poniższe przykłady kodu ilustrują każdego z tych scenariuszy.

Przypadek 1: Zbyt skomplikowane wyrażenia.W tym przykładzie lista counter ma być int option ref, ale nie jest zdefiniowany jako prostą wartością niezmienne.

let counter = ref None
// Adding a type annotation fixes the problem:
let counter : int option ref = ref None

Przypadek 2: Przy użyciu konstrukcji nongeneralizable do definiowania funkcji rodzajowy.W tym przykładzie konstrukcji jest nongeneralizable, ponieważ pociąga za sobą częściowe stosowanie argumenty funkcji.

let maxhash = max << hash
// The following is acceptable because the argument for maxhash is explicit:
let maxhash obj = (max << hash) obj

W przypadku 3: Dodawanie parametrem ekstra, nieużywane.Ponieważ wyrażenie to nie jest wystarczająco prosty Generalizacja, kompilator generuje błąd ograniczenia wartości.

let emptyList10 = Array.create 10 []
// Adding an extra (unused) parameter makes it a function, which is generalizable.
let emptyList10 () = Array.create 10 []

W przypadku 4: Dodawanie parametrów typu.

let arrayOf10Lists = Array.create 10 []
// Adding a type parameter and type annotation lets you write a generic value.
let arrayOf10Lists<'T> = Array.create 10 ([]:'T list)

W ostatnim przypadku wartość staje się funkcja typu, który może służyć do tworzenia wartości różnych typów, na przykład w następujący sposób:

let intLists = arrayOf10Lists<int>
let floatLists = arrayOf10Lists<float>

Zobacz też

Informacje

Wnioskowanie o typie (F#)

Typy ogólne (F#)

Statycznie rozwiązywane parametry typu (F#)

Ograniczenia (F#)