Haskell - Types 和 Type 类
Haskell 是一种函数式语言,并且它是严格类型的,这意味着整个应用程序中使用的数据类型将在编译时为编译器所知。
内置类型类
在 Haskell 中,每个语句都被视为一个数学表达式,该表达式的类别称为Type。 您可以说"Type"是编译时使用的表达式的数据类型。
要了解有关Type的更多信息,我们将使用":t"命令。 一般来说,Type可以被视为一个值,而Type Class可以被视为一组相似类型的类型。 在本章中,我们将了解不同的内置类型。
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
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"修改为"Integer"并观察差异。
fType :: Integer -> Integer -> Integer fType x y = x*x + y*y main = print (fType 212124454 4454545445455454545445445454544545)
现在,它将产生以下输出 −
sh-4.3$ main 1984297512562793395882644631364297686099210302577374055141
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
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
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
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 足够智能,可以在声明之前捕获类型。 在本教程的后续章节中,我们将看到不同的类型和 Type 类如何使 Haskell 成为强类型语言。
EQ Type 类
EQ 类型类是一个接口,提供测试表达式相等性的功能。 任何想要检查表达式相等性的类型类都应该是此 EQ 类型类的一部分。
上面提到的所有标准 Type 类都是此 EQ 类的一部分。 每当我们使用上述任何类型检查是否相等时,我们实际上都是在调用 EQ Type 类。
在下面的示例中,我们在内部使用 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 Type 类
Ord 是另一个接口类,它为我们提供排序功能。 到目前为止,我们使用的所有Type(类型)都是这个Ord接口的一部分。 与EQ接口一样,Ord接口也可以使用">", "<", "<=", ">=", "compare"来调用。
请在下面的示例中使用此类型类的"compare"(比较)功能。
main = print (4 <= 2)
这里,Haskell 编译器将检查 4 是否小于或等于 2。由于不小于或等于 2,代码将产生以下输出 −
sh-4.3$ main False
Show
Show 具有将其参数打印为字符串的功能。 无论它的参数是什么,它总是将结果打印为字符串。 在下面的示例中,我们将使用此接口打印整个列表。 "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
在这里,我们将一个字符串变量("12")传递给 readInt 方法,该方法在转换后返回 12(一个 Int 值)。 这是它的输出 −
sh-4.3$ main 12
Enum
Enum 是 Type 类的另一种类型,它支持 Haskell 中的顺序或有序功能。 这个Type类可以通过Succ、Pred、Bool、Char等命令访问
以下代码显示如何查找 12 的后继值。
main = print (succ 12)
它将产生以下输出 −
sh-4.3$ main 13
界限(Bounded)
所有具有上限和下限的类型都属于此类型类。 例如,Int类型数据的最大界限为"9223372036854775807",最小c为"-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 Type Class 的子类。 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