Haskell型別和Type類


Haskell是一種函式語言,它是嚴格型別化的,Haskell編譯器在編譯時知道整個應用程式中使用的資料型別。

1. 內建型別類

在Haskell中,每個語句都被視為數學表示式,並且此表示式的類別稱為型別(Type)。可以說Type是在編譯時使用的表示式的資料型別。

要了解有關型別的更多資訊,可以使用:t命令。以通用的方式可以將型別視為值,而可以將型別類視為一組相似型別的型別。在本章中,我們將學習不同的內建型別。

2. Int

Int是代表Integer型別資料的型別類。2147483647-2147483647範圍內的每個整數都屬於Int型別類。在下面的範例中,函式fType()將根據定義的型別來表示。

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

在這裡,我們將函式fType()的型別設定為int。函式採用兩個int值,並返回一個int值。如果編譯並執行這段程式碼,那麼它將產生以下輸出:

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

3. Integer

Integer可以視為Int的超集。此值不受任何數位限制,因此Integer可以是任何長度,沒有任何限制。要了解IntInteger型別之間的基本區別,修改上面的程式碼如下所示:

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

如果編譯以上程式碼,將丟擲以下錯誤訊息:

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

發生此錯誤是因為函式fType()期望一個Int型別值,並且傳遞了一些大的Int型別值。為了避免此錯誤,將Int修改型別Integer並觀察區別。

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

現在,它將產生以下輸出:

sh-4.3$ main
1984297512562793395882644631364297686099210302577374055141

4. Float

看看下面的程式碼,它顯示了Float型別如何在Haskell中工作:


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

該函式將兩個浮點值作為輸入,並產生另一個浮點值作為輸出。當編譯並執行此程式碼時,它將產生以下輸出:

sh-4.3$ main
20.689999

5. Double

Double是浮點數,它的末尾具有雙精度。看下面的範例程式碼:

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

當編譯並執行此程式碼時,它將產生以下輸出:

sh-4.3$ main 
21.0697

6. Bool

Bool是布林型別。它的值可以是TrueFalse。執行以下程式碼以了解Bool型別在Haskell中的工作方式。

main = do  
   let x = True 

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

在這裡,我們將變數x定義為布林型,並將其與另一個布林值進行比較以檢查其值。當編譯並執行此程式碼時,它將產生以下輸出:

sh-4.3$ main
X is not a Bool Type

7. Char

Char代表字元。單引號內的所有內容均視為字元。在下面的程式碼中,我們修改了前面的fType()函式以接受Char值並將Char值返回為輸出。

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

上面的程式碼將呼叫fType()函式,引數為char型別值為v,但它將返回另一個char值,即K。下面是它的輸出:

sh-4.3$ main 
'K'

請注意,不用顯式使用這些型別,因為Haskell足夠聰明,可以在宣告型別之前捕獲型別。在本教學的後續章節中,我們將了解不同的型別和型別類如何使Haskell成為強型別語言。

8. EQ型別類

EQ型別類是提供測試表示式是否相等的功能的介面。檢查表示式是否相等的型別類都應屬於此EQ型別類。

上面提到的所有標準型別類都是此EQ類的一部分。每當我們使用上述任何一種型別檢查任何相等性時,實際上都是在呼叫EQ型別類。

在以下範例中,在內部使用==/=操作使用EQ型別。

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

它將產生以下輸出:

sh-4.3$ main 
The values are not Equal

9. Ord型別類

Ord是另一個提供排序功能的介面類。到目前為止,使用的所有型別都是Ord介面的一部分。與EQ介面類似,可以使用><<=>=compare來呼叫Ord介面。

在下面範例中使用此型別類的「比較」功能。

main = print (4 <= 2)

在這裡,Haskell編譯器將檢查4是否小於或等於2。由於4不是小於或等於2,因此程式碼將產生以下輸出:

sh-4.3$ main 
False

10. Show

Show具有將引數列印為字串的功能。無論引數是什麼,它始終將結果列印為字串。在以下範例中,我們將使用此介面列印整個列表。Show可用於呼叫此介面。

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

它將在控制台上產生以下輸出。在這裡,雙引號表示它是字串型別的值。

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

11. Read

Read介面的功能與顯示相同,但不會以字串格式列印結果。在以下程式碼中,使用read介面讀取字串值並轉換為Int值。

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

在這裡,將字串變數("12")傳遞給readInt方法,該方法在轉換後又返回12(Int值)。下面是它的輸出:

sh-4.3$ main 
12

12. Enum

列舉是Type類的另一種型別,可在Haskell中啟用順序或有序功能。可以通過諸如SuccPredBoolChar等命令存取此Type類。

以下程式碼顯示了如何查詢12的後繼值:

main = print (succ 12)

它將在控制台上產生以下輸出:

sh-4.3$ main
13

13. Bounded

具有上限和下限的所有型別都屬於此Type類。例如,Int型別資料的最大範圍為9223372036854775807,最小範圍為-9223372036854775808

以下程式碼顯示Haskell如何確定Int型別的最大和最小範圍。

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

它將在控制台上產生以下輸出:

sh-4.3$ main
9223372036854775807
-9223372036854775808

您可以嘗試查詢CharFloatBool型別的最大和最小界限。

14. Num

Num型別類用於數位運算。諸如IntIntegerFloatDouble之類的型別都屬於此Type類。看一下下面的程式碼-

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

它將在控制台上產生以下輸出:

sh-4.3$ main
2
2.0

15. Integral

整數可以視為Num Type類的子類。Num Type類儲存所有型別的數位,而Integral型別類僅用於整數。IntInteger是此Type類下的型別。

16. Floating

Integral一樣,Floating也是Num Type類的一部分,但它僅包含浮點數。因此,FloatDouble屬於此類型別。

17. 自定義Type類

與任何其他程式設計語言一樣,Haskell允許開發人員定義使用者定義的型別。在下面的範例中,我們將建立一個使用者定義的型別並使用它。

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

在這裡,建立了一個名為Area的新型別。接下來使用這個型別來計算圓的面積。在上面的範例中,surface是一個函式,該函式將Area作為輸入並產生Float作為輸出。

請記住,data在此處是關鍵字,Haskell中所有使用者定義的型別始終以大寫字母開頭。

它將產生以下輸出:

sh-4.3$ main
314.15927