Haskell是一種函式語言,它是嚴格型別化的,Haskell編譯器在編譯時知道整個應用程式中使用的資料型別。
在Haskell中,每個語句都被視為數學表示式,並且此表示式的類別稱為型別(Type
)。可以說Type
是在編譯時使用的表示式的資料型別。
要了解有關型別的更多資訊,可以使用:t
命令。以通用的方式可以將型別視為值,而可以將型別類視為一組相似型別的型別。在本章中,我們將學習不同的內建型別。
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
Integer
可以視為Int
的超集。此值不受任何數位限制,因此Integer
可以是任何長度,沒有任何限制。要了解Int
和Integer
型別之間的基本區別,修改上面的程式碼如下所示:
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
看看下面的程式碼,它顯示了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
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
Bool是布林型別。它的值可以是True
或False
。執行以下程式碼以了解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
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成為強型別語言。
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
Ord是另一個提供排序功能的介面類。到目前為止,使用的所有型別都是Ord
介面的一部分。與EQ介面類似,可以使用>
,<
,<=
,>=
,compare
來呼叫Ord介面。
在下面範例中使用此型別類的「比較」功能。
main = print (4 <= 2)
在這裡,Haskell編譯器將檢查4
是否小於或等於2
。由於4
不是小於或等於2
,因此程式碼將產生以下輸出:
sh-4.3$ main
False
Show
具有將引數列印為字串的功能。無論引數是什麼,它始終將結果列印為字串。在以下範例中,我們將使用此介面列印整個列表。Show
可用於呼叫此介面。
main = print (show [1..10])
它將在控制台上產生以下輸出。在這裡,雙引號表示它是字串型別的值。
sh-4.3$ main
"[1,2,3,4,5,6,7,8,9,10]"
Read
介面的功能與顯示相同,但不會以字串格式列印結果。在以下程式碼中,使用read
介面讀取字串值並轉換為Int
值。
main = print (readInt "12")
readInt :: String -> Int
readInt = read
在這裡,將字串變數("12"
)傳遞給readInt
方法,該方法在轉換後又返回12
(Int值)。下面是它的輸出:
sh-4.3$ main
12
列舉是Type
類的另一種型別,可在Haskell中啟用順序或有序功能。可以通過諸如Succ
,Pred
,Bool
,Char
等命令存取此Type
類。
以下程式碼顯示了如何查詢12
的後繼值:
main = print (succ 12)
它將在控制台上產生以下輸出:
sh-4.3$ main
13
具有上限和下限的所有型別都屬於此Type
類。例如,Int
型別資料的最大範圍為9223372036854775807
,最小範圍為-9223372036854775808
。
以下程式碼顯示Haskell如何確定Int
型別的最大和最小範圍。
main = do
print (maxBound :: Int)
print (minBound :: Int)
它將在控制台上產生以下輸出:
sh-4.3$ main
9223372036854775807
-9223372036854775808
您可以嘗試查詢Char
,Float
和Bool
型別的最大和最小界限。
Num
型別類用於數位運算。諸如Int
,Integer
,Float
和Double
之類的型別都屬於此Type
類。看一下下面的程式碼-
main = do
print(2 :: Int)
print(2 :: Float)
它將在控制台上產生以下輸出:
sh-4.3$ main
2
2.0
整數可以視為Num Type
類的子類。Num Type
類儲存所有型別的數位,而Integral
型別類僅用於整數。Int
和Integer
是此Type
類下的型別。
像Integral
一樣,Floating
也是Num Type
類的一部分,但它僅包含浮點數。因此,Float
和Double
屬於此類型別。
與任何其他程式設計語言一樣,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