类型和类型类( Types and Type Class)
Haskell是一种函数式语言,它是严格类型的,这意味着整个应用程序中使用的数据类型在编译时将为编译器所知。
内置类型类
在Haskell中,每个语句都被视为一个数学表达式,该表达式的类别被称为Type 。 您可以说“Type”是编译时使用的表达式的数据类型。
要了解有关Type更多信息,我们将使用“:t”命令。 通常, Type可以被视为一个值,而Type Class可以被认为是一组类似的类型。 在本章中,我们将了解不同的内置类型。
诠释
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
Integer可以被视为Int的超集。 该值不受任何数字的限制,因此整数可以是任意长度而没有任何限制。 要查看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”并观察差异。
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
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”定义为Bool,并将其与另一个布尔值进行比较以检查其原始性。 它将产生以下输出 -
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)
上面的代码将使用char值'v'调用fType()函数,但它返回另一个char值,即'K'。 这是它的输出 -
sh-4.3$ main
'K'
请注意,我们不会显式使用这些类型,因为Haskell足够智能,可以在声明之前捕获类型。 在本教程的后续章节中,我们将看到不同类型和类型类如何使Haskell成为强类型语言。
EQ类型
EQ类型类是一个接口,它提供测试表达式相等性的功能。 任何想要检查表达式相等性的Type类都应该是此EQ Type类的一部分。
上面提到的所有标准类型类都是此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是另一个接口类,它为我们提供了排序功能。 到目前为止我们使用的所有types都是这个Ord接口的一部分。 与EQ接口一样,Ord接口可以使用“”“,”“”,“”=“,”“=”,“比较”来调用。
请在下面的示例中找到我们使用此类型类的“比较”功能的示例。
main = print (4 <= 2)
这里,Haskell编译器将检查4是否小于或等于2.由于它不是,代码将产生以下输出 -
sh-4.3$ main
False
Show
Show具有将其参数作为String打印的功能。 无论它的论点是什么,它总是将结果打印为String。 在以下示例中,我们将使用此界面打印整个列表。 “show”可用于调用此接口。
main = print (show [1..10])
它将在控制台上生成以下输出。 这里,双引号表示它是String类型值。
sh-4.3$ main
"[1,2,3,4,5,6,7,8,9,10]"
Read
Read接口与Show相同,但不会以String格式打印结果。 在下面的代码中,我们使用read接口读取字符串值并将其转换为Int值。
main = print (readInt "12")
readInt :: String -> Int
readInt = read
这里,我们将一个String变量(“12”)传递给readInt方法,该方法在转换后返回12(一个Int值)。 这是它的输出 -
sh-4.3$ main
12
Enum
Enum是另一种Type类,它在Haskell中启用顺序或有序功能。 可以通过Succ, Pred, Bool, Char等命令访问此Type类。
以下代码显示了如何查找12的后继值。
main = print (succ 12)
它将产生以下输出 -
sh-4.3$ main
13
Bounded
所有具有上限和下限的类型都属于此类类。 例如, 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
Integral
Integral可以被认为是Num类型的子类。 Num Type类包含所有类型的数字,而Integral类类仅用于整数。 Int和Integer是此Type类下的类型。
Floating
与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