2011-06-24 18 views
13

Walczę z notacją podpisu typu F #. Na przykład załóżmy, że masz Fold funkcję:Jak odczytać podpisy typu F #?

let rec Fold combine acc l = 
... 

które mogą mieć tego typu podpis:

('a -> 'b -> 'a) -> 'a -> list<'b> -> 'a 

które czytałem jako

funkcję, która ma trzy argumenty:

  • Funkcja, która pobiera "a, a 'b i zwraca a'
  • 'a
  • listę' b

i zwraca „a.

Ale wtedy byłoby bardziej sensowne dla mojego jaskiniowcy mózg do wyrażania go jako

('a, 'b -> 'a), 'a, list<'b> -> 'a 

Jestem pewien, że istnieje powód, dlaczego semantyczny parametry są rozdzielone ze strzałką dokładnie tak samo jak funkcja typ zwrotu, ale jakoś go brakuje i nie znalazłem dotąd jasnego wyjaśnienia w książkach/artykułach. Za każdym razem, gdy widzę podpis typu, muszę poświęcić mu trochę czasu, aby go zrozumieć. Czuję, że po prostu tę małą część układanki, która sprawia, że ​​"odszyfrowywanie" jest oczywiste.

Czy ktoś może mnie oświecić?

Odpowiedz

15

Jestem pewien, że jest semantyczny powodem dlaczego parametry są oddzielone z strzałką dokładnie takie same sposób jako typ zwracany funkcji , ale jakoś jestem go brakuje i nie znalazłem jak dotąd jasnego wyjaśnienia w książkach/artykułach.

Czytanie pierwszej funkcji jest poprawne. W celu natychmiastowego odszyfrowania podpisy typu są wyrażane w następujący sposób:

val functionName = inputType1 -> inputType2 -> ... -> inputTypeN -> returnType 

Ogólnie notacja strzałkowa wskazuje, że funkcja jest dostępna do curry.

// val add4 : int -> int -> int -> int -> int 
let add4 a b c d = a + b + c + d;; 

// val f : (int -> int) 
let f = add4 1 2 3 // returns (int -> int) waiting for last argument 

Ponieważ funkcja jest curry, można technicznie napisać to tak:

// val add4 : int -> int -> int -> int -> int 
let add4 = (fun a -> (fun b -> (fun c -> (fun d -> a + b + c + d))));; 

// val f : (int -> int) 
let f = fun x -> add4 1 2 3 x 

Jeśli myślisz o tym, podpis add4 jest odpowiednikiem tego:

val add4 : int -> (int -> (int -> (int -> int))) 

I uważamy, że używamy notacji strzałkowej, ponieważ przypomina strukturę funkcji, gdy jawnie curry argumenty, jak pokazano powyżej.

+0

Jasne wyjaśnienie, dzięki. Po przeczytaniu tego zastanawiam się, jak go wcześniej nie widziałem ... –

+0

Nie sądzę, że to jest powód, dla którego używamy notacji strzałkowej (w typach). Wszakże w rachunku lambda używamy "->" w składni typów, ale "." w składni terminów. [Może oczywiście być prawdą, że używamy -> w terminach w F #, ponieważ używamy -> w typach i. został już zabrany.] – petebu

6

Podpisy pisane są w ten sposób ze względu na to, co nazywa się Currying. Nieco dokładniejszym sposobem opisania funkcji jest funkcja (która zajmuje 'a i zwraca funkcję z 'b do 'a) i zwraca funkcję, która pobiera 'a i zwraca funkcję z list<'b> do . Z tego powodu sygnaturę typu można przepisać jako

('a -> 'b -> 'a) -> ('a -> (list<'b> -> 'a)) 
+0

Tak samo jak w przypadku kvb, dobre wytłumaczenie, dzięki - niestety mogę zaakceptować tylko jedną odpowiedź –

2

Powodem tego jest w Programowaniu funkcjonalnym, że każda funkcja ma tylko jeden parametr.

Więc powiedzmy, że masz funkcję o nazwie Suma jako:

int -> int -> int 

trwa 2 int i zwraca jeden int. Teraz jeśli wywołasz tę funkcję, po prostu przekazując jedną int, nie otrzymasz błędu kompilatora, a wartość zwracana będzie typu int -> int. Więc widzisz, że ta notacja strzałkowa pasuje do tego zachowania. To zachowanie jest znane jako Currying. Check out: http://en.wikipedia.org/wiki/Currying

+0

ładny przykład, doskonałe uzupełnienie powyższych odpowiedzi! Ale schönfinkeling jest o tyle lepszą nazwą :-) –

5

Można napisać podobną funkcję w F #, który ma typ jakbyś proponuje (ale w F # to być zapisane jako ('a * 'b -> 'a) * 'a * list<'b> -> 'a Jednak zaletą istniejącej funkcji jest to, że łatwo. częściowo zastosuj go, podając tylko przedrostek argumentów.Na przykład:

let sum = List.fold (+) 0 

Korzystanie swoją definicję, trzeba by napisać

let sum l = List.fold((fun (x,y) -> x + y), 0, l) 
+0

Również bardzo dobrze, szkoda, że ​​można zaakceptować tylko jedną odpowiedź. –

Powiązane problemy