2015-01-29 22 views
5

Jest to prawdopodobnie bardzo podstawowe pytanie, ale wydaje się, że nie zostało ono uwzględnione w SO.Haskell- (typ deklaracja) co to jest "a"?

Niedawno odbyła się Haskell i aż do teraz wpisać deklaracje składało się głównie z następujących powodów:

Int 
Bool 
Float 
etc, etc 

Teraz jestem coraz w listach i widzę deklaracji typu, które używają a, takie jak na poniższym funkcji który dokonuje iteracji asocjacyjną listy:

contains :: Int -> [(Int,a)] -> [a] 
contains x list = [values | (key,values)<-list, x==key] 

Może ktoś dostarczyć wyjaśnienie, co to a jest i jak to działa? Z obserwacji wydaje się reprezentować każdy typ. Czy to znaczy, że mogę wprowadzić dowolną listę dowolnego typu jako parametr?

Odpowiedz

12

Tak, masz rację, reprezentuje "dowolny typ" - ograniczenie polegające na tym, że wszystkie a s w danym typie podpisu muszą być zgodne z tym samym typem. Możesz więc wprowadzić listę dowolnego typu, ale gdy użyjesz contains do wyszukania wartości na liście, szukana wartość musi być tego samego typu co elementy listy - co oczywiście ma sens.

+8

Co równie ważne, "a" nie jest specjalne: * każdy * mały identyfikator oznacza to. Jest to zmienna * typu * i możliwe jest istnienie wielu różnych zmiennych typu w tym samym sygnaturze. Na przykład 'const :: a -> b -> a' przyjmuje dwa argumenty, każdy w ogóle typu i zwraca wartość tego samego typu, co pierwsze wejście. – amalloy

+2

Widzę, jest bardzo ogólna. Sądzę więc, że w większości przypadków "a" generalnie reprezentuje elementy, których moja funkcja tak naprawdę nie używa lub zmienia, za dużo. – Bolboa

+1

@Bolboa: Tak, jest to ściśle związane z pojęciem "generics" w innych językach. I tak, jeśli typ jest całkowicie ogólny, niewiele można zrobić bezpośrednio na samą wartość. Haskell ma sposób na dostarczenie większej ilości informacji o typie (na przykład "można porównać dla równości", "można wydrukować", "można traktować jak liczbę"), co pozwala na większe przetwarzanie wartości ; jeśli jesteś zainteresowany tym, to szukaj "klas" w dokumentacji lub samouczku. – psmears

1

Haskell, wielkie typy konkretne typy (Int, Bool) lub typu konstruktory (Maybe, Either), natomiast małe są typy zmienne typu. Funkcja jest niejawnie generic we wszystkich zmiennych typu, którego używa, więc tak:

contains :: Int -> [(Int, a)] -> [a] 

jest skrótem dla tego *:

contains :: forall a. Int -> [(Int, a)] -> [a] 

w C++, forall jest orkisz template:

template<typename a> 
list<a> contains(int, list<pair<int, a>>); 

W języku Java i C# jest napisane ortograficznie z nawiasami ostrymi:

list<a> contains<a>(int, list<pair<int, a>>); 

Oczywiście, w tych językach, zmienne typu rodzajowego są często nazywane T, U, V, natomiast w Haskell są one często nazywane a, b, c. To tylko różnica konwencji.

* Ta składnia jest włączona przez flagę -XExplicitForAll w GHC, a także inne rozszerzenia.

+0

O wiele bardziej użyteczny: '-XScopedTypeVariables'. Ponadto, szablony C++ wydają się być z natury nieco inne niż zmienne typu Haskell/ML/... lub nawet Java Generics. – dfeuer