Haskell - Typy i klasa typów

Haskell jest językiem funkcjonalnym i jest ściśle typizowany, co oznacza, że ​​typ danych używany w całej aplikacji będzie znany kompilatorowi w czasie kompilacji.

Wbudowana klasa typu

W Haskell każde stwierdzenie jest uważane za wyrażenie matematyczne, a kategoria tego wyrażenia jest nazywana jako Type. Można powiedzieć, że „Typ” to typ danych wyrażenia użytego w czasie kompilacji.

Aby dowiedzieć się więcej o Type, użyjemy polecenia „: t”. W ogólny sposóbType można uznać za wartość, podczas gdy Type Classmożna uznać za zbiór podobnych typów. W tym rozdziale poznamy różne typy wbudowane.

Int

Intjest klasą typu reprezentującą dane typu Integer. Każda liczba całkowita z zakresu od 2147483647 do -2147483647 jest objęta rozszerzeniemIntklasa typu. W poniższym przykładzie funkcjafType() będzie zachowywać się zgodnie ze zdefiniowanym typem.

fType :: Int -> Int -> Int 
fType x y = x*x + y*y
main = print (fType 2 4)

Tutaj ustawiliśmy typ funkcji fType() tak jak int. Funkcja zajmuje dwaint wartości i zwraca jeden intwartość. Jeśli skompilujesz i wykonasz ten fragment kodu, wygeneruje on następujący wynik -

sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts 
sh-4.3$ main
20

Liczba całkowita

Integer można uznać za nadzbiór Int. Ta wartość nie jest ograniczona żadną liczbą, dlatego liczba całkowita może mieć dowolną długość bez żadnych ograniczeń. Aby zobaczyć podstawową różnicę międzyInt i Integer typów, zmodyfikujmy powyższy kod w następujący sposób -

fType :: Int -> Int -> Int 
fType x y = x*x + y*y 
main = print (fType 212124454 44545454454554545445454544545)

Jeśli skompilujesz powyższy fragment kodu, zostanie wyrzucony następujący komunikat o błędzie -

main.hs:3:31: Warning:            
   Literal 44545454454554545445454544545 is out of the Int range -
   9223372036854775808..9223372036854775807 
Linking main ...

Ten błąd wystąpił, ponieważ nasza funkcja fType () oczekiwała jednej wartości typu Int i przekazujemy naprawdę dużą wartość typu Int. Aby uniknąć tego błędu, zmieńmy typ „Int” na „Integer” i obserwujmy różnicę.

fType :: Integer -> Integer -> Integer 
fType x y = x*x + y*y 
main = print (fType 212124454 4454545445455454545445445454544545)

Teraz wygeneruje następujący wynik -

sh-4.3$ main
1984297512562793395882644631364297686099210302577374055141

Pływak

Spójrz na następujący fragment kodu. Pokazuje, jak działa typ Float w Haskell -

fType :: Float -> Float -> Float 
fType x y = x*x + y*y 
main = print (fType 2.5 3.8)

Funkcja przyjmuje dwie wartości zmiennoprzecinkowe jako dane wejściowe i zwraca inną wartość zmiennoprzecinkową jako dane wyjściowe. Kiedy kompilujesz i wykonujesz ten kod, wygeneruje on następujący wynik -

sh-4.3$ main
20.689999

Podwójnie

Doublejest liczbą zmiennoprzecinkową z podwójną precyzją na końcu. Spójrz na następujący przykład -

fType :: Double -> Double -> Double 
fType x y = x*x + y*y 
main = print (fType 2.56 3.81)

Po wykonaniu powyższego fragmentu kodu wygeneruje on następujące dane wyjściowe -

sh-4.3$ main 
21.0697

Bool

Booljest typem boolowskim. Może mieć wartość True lub False. Wykonaj następujący kod, aby zrozumieć, jak działa typ Bool w Haskell -

main = do  
   let x = True 
   
   if x == False 
      then putStrLn "X matches with Bool Type" 
   else putStrLn "X is not a Bool Type"

Tutaj definiujemy zmienną „x” jako wartość logiczną i porównujemy ją z inną wartością logiczną, aby sprawdzić jej oryginalność. Wytworzy następujący wynik -

sh-4.3$ main
X is not a Bool Type

Zwęglać

Znaki reprezentują postacie. Cokolwiek w pojedynczym cudzysłowie jest traktowane jako znak. W poniższym kodzie zmodyfikowaliśmy nasz poprzedni plikfType() funkcja, aby zaakceptować wartość Char i zwrócić wartość Char jako dane wyjściowe.

fType :: Char-> Char 
fType x = 'K' 
main = do  
   let x = 'v' 
   print (fType x)

Zadzwoni powyższy fragment kodu fType() funkcja z charwartość „v”, ale zwraca inną wartość znaku, to jest „K”. Oto jego wynik -

sh-4.3$ main 
'K'

Zauważ, że nie zamierzamy używać tych typów jawnie, ponieważ Haskell jest wystarczająco inteligentny, aby złapać typ przed jego zadeklarowaniem. W kolejnych rozdziałach tego samouczka zobaczymy, jak różne typy i klasy Type sprawiają, że Haskell jest językiem silnie typizowanym.

Klasa typu EQ

EQklasa typu to interfejs, który udostępnia funkcję testowania równości wyrażenia. Każda klasa Type, która chce sprawdzić równość wyrażenia, powinna być częścią tej klasy EQ Type.

Częścią tego są wszystkie wymienione powyżej standardowe klasy typów EQklasa. Ilekroć sprawdzamy jakąkolwiek równość przy użyciu któregokolwiek z typów wymienionych powyżej, w rzeczywistości wykonujemy wywołanieEQ klasa typu.

W poniższym przykładzie używamy EQ Wpisz wewnętrznie, używając operacji „==” lub „/ =”.

main = do 
   if 8 /= 8 
      then putStrLn "The values are Equal" 
   else putStrLn "The values are not Equal"

Da to następujący wynik -

sh-4.3$ main 
The values are not Equal

Klasa typu zamówienia

Ordto kolejna klasa interfejsu, która daje nam funkcjonalność zamawiania. Wszystkietypes których używaliśmy do tej pory, są tego częścią Ordberło. Podobnie jak interfejs EQ, interfejs Ord można wywołać za pomocą ">", "<", "<=", "> =", "porównaj".

Poniżej znajduje się przykład, w którym użyliśmy funkcji „porównaj” tej klasy typu.

main = print (4 <= 2)

W tym przypadku kompilator Haskell sprawdzi, czy 4 jest mniejsze lub równe 2. Ponieważ tak nie jest, kod zwróci następujący wynik -

sh-4.3$ main 
False

Pokazać

Showma funkcję wypisywania argumentu jako String. Cokolwiek może być jego argumentem, zawsze wypisuje wynik jako String. W poniższym przykładzie wydrukujemy całą listę za pomocą tego interfejsu. Do wywołania tego interfejsu można użyć „show”.

main = print (show [1..10])

Na konsoli wygeneruje następujące dane wyjściowe. Tutaj podwójne cudzysłowy wskazują, że jest to wartość typu String.

sh-4.3$ main 
"[1,2,3,4,5,6,7,8,9,10]"

Czytać

Readinterfejs robi to samo co Show, ale nie wypisze wyniku w formacie String. W poniższym kodzie użyliśmyread interfejs, aby odczytać wartość ciągu i przekonwertować ją na wartość Int.

main = print (readInt "12") 
readInt :: String -> Int 
readInt = read

Tutaj przekazujemy zmienną typu String („12”) do pliku readInt, która z kolei zwraca 12 (wartość Int) po konwersji. Oto jego wynik -

sh-4.3$ main 
12

Enum

Enumto kolejny typ klasy Type, który umożliwia sekwencyjną lub uporządkowaną funkcjonalność w Haskell. Dostęp do tej klasy Type można uzyskać za pomocą poleceń, takich jakSucc, Pred, Bool, Charitp.

Poniższy kod pokazuje, jak znaleźć następną wartość 12.

main = print (succ 12)

Wytworzy następujący wynik -

sh-4.3$ main
13

Zobowiązany

Wszystkie typy posiadające górną i dolną granicę należą do tej klasy typów. Na przykład,Int typ danych ma maksymalny limit „9223372036854775807” i minimalny limit „-9223372036854775808”.

Poniższy kod pokazuje, jak Haskell określa maksymalne i minimalne ograniczenie typu Int.

main = do 
   print (maxBound :: Int) 
   print (minBound :: Int)

Wytworzy następujący wynik -

sh-4.3$ main
9223372036854775807
-9223372036854775808

Teraz spróbuj znaleźć maksymalne i minimalne ograniczenie typów Char, Float i Bool.

Num

Ta klasa typu jest używana do operacji numerycznych. Typy, takie jak Int, Integer, Float i Double, należą do tej klasy Type. Spójrz na następujący kod -

main = do 
   print(2 :: Int)  
   print(2 :: Float)

Wytworzy następujący wynik -

sh-4.3$ main
2
2.0

Całka

Integralmożna uznać za podklasę klasy Num Type. Klasa Num Type zawiera wszystkie typy liczb, natomiast klasa typu Integral jest używana tylko dla liczb całkowitych. Int i Integer to typy w tej klasie Type.

Ruchomy

Podobnie jak Integral, Floating jest również częścią klasy Num Type, ale przechowuje tylko liczby zmiennoprzecinkowe. W związku z tym,Float i Double należą do tej klasy typu.

Klasa typu niestandardowego

Jak każdy inny język programowania, Haskell umożliwia programistom definiowanie typów zdefiniowanych przez użytkownika. W poniższym przykładzie utworzymy typ zdefiniowany przez użytkownika i użyjemy go.

data Area = Circle Float Float Float  
surface :: Area -> Float   
surface (Circle _ _ r) = pi * r ^ 2   
main = print (surface $ Circle 10 20 10 )

Tutaj stworzyliśmy nowy typ o nazwie Area. Następnie używamy tego typu do obliczenia pola koła. W powyższym przykładzie „powierzchnia” jest funkcją, która przyjmujeArea jako wkład i produkuje Float jako wyjście.

Należy pamiętać, że słowo „dane” jest tutaj słowem kluczowym i wszystkie typy zdefiniowane przez użytkownika w Haskell zawsze zaczynają się od dużej litery.

Wytworzy następujący wynik -

sh-4.3$ main
314.15927