Haskell - 基本数据模型



Haskell 是一种纯函数式编程语言,因此它比其他编程语言更具交互性和智能性。本章我们将学习 Haskell 的基本数据模型,这些模型实际上是预定义的,或者以某种智能方式解码到计算机内存中。

在本教程中,我们将使用网站上提供的 Haskell 在线平台(https://tutorialspoint.com/codingground.htm)。

数字

Haskell 足够智能,可以将某些数字解码为数字。因此,您无需像在其他编程语言中那样外部声明其类型。例如,转到您的 prelude 命令提示符,运行“2+2”并按 Enter 键。

sh-4.3$ ghci 
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> 2+2

您将收到以下输出。

4

在上面的代码中,我们只是将两个数字作为参数传递给 GHCI 编译器,而没有预定义它们的类型,但编译器可以轻松地将这两个输入解码为数字。

现在,让我们尝试更复杂的数学计算,看看我们的智能编译器是否能给出正确的输出。尝试使用“15+(5*5)-40”。

Prelude> 15+(5*5)-40 

根据预期输出,上述表达式结果为“0”。

0

字符

与数字一样,Haskell 可以智能地识别作为输入给出的字符。转到您的 Haskell 命令提示符,并使用双引号或单引号输入任何字符。

让我们提供以下行作为输入并检查其输出。

Prelude> :t "a" 

它将产生以下输出:

"a" :: [Char] 

请记住,在提供输入时使用 (:t)。在上面的例子中,(:t) 用于包含与输入相关的特定类型。我们将在接下来的章节中学习更多关于这种类型的知识。

让我们来看一个例子,在这个例子中,我们传递了一些无效的字符输入,这导致了错误。

Prelude> :t a 
<interactive>:1:1: Not in scope: 'a'  

Prelude> a 
<interactive>:4:1: Not in scope: 'a' 

通过错误消息“<interactive>:4:1: Not in scope: `a'”,Haskell 编译器警告我们它无法识别您的输入。Haskell 是一种所有内容都用数字表示的语言。

Haskell 遵循传统的 ASCII 编码方式。让我们来看下面的例子以了解更多信息:

Prelude> '\97' 
'a'  
Prelude> '\67' 
'C' 

看看您的输入是如何被解码成 ASCII 格式的。

字符串

字符串只不过是字符的集合。使用字符串没有特定的语法,但 Haskell 遵循使用双引号表示字符串的传统风格。

让我们来看一个例子,在这个例子中,我们传递字符串“Tutorialspoint.com”。

Prelude> :t "tutorialspoint.com" 

它将在屏幕上产生以下输出:

"tutorialspoint.com" :: [Char] 

看看整个字符串是如何被解码为仅包含 Char 的数组的。让我们转向其他数据类型及其语法。一旦我们开始实际练习,我们就会习惯所有数据类型及其用法。

布尔值

布尔数据类型与其他数据类型一样非常简单。让我们来看一个例子,我们将使用一些布尔输入(如“True”或“False”)使用不同的布尔运算。

Prelude> True && True 
True  
Prelude> True && False 
False   
Prelude> True || True 
True  
Prelude> True || False 
True

在上面的例子中,我们不需要提到“True”和“False”是布尔值。Haskell 本身可以解码它并执行相应的操作。让我们将输入修改为“true”或“false”。

Prelude> true 

它将产生以下输出:

<interactive>:9:1: Not in scope: 'true' 

在上面的例子中,Haskell 无法区分“true”和数字值,因此我们的输入“true”不是数字。因此,Haskell 编译器抛出一个错误,指出我们的输入不在其作用域内。

列表和列表推导

与其他数据类型一样,列表也是 Haskell 中非常有用的数据类型。例如,[a,b,c] 是一个字符列表,因此,根据定义,列表是由逗号分隔的相同数据类型的集合。

与其他数据类型一样,您不需要将列表声明为列表。Haskell 足够智能,可以通过查看表达式中使用的语法来解码您的输入。

让我们来看下面的例子,它展示了 Haskell 如何处理列表。

Prelude> [1,2,3,4,5] 

它将产生以下输出:

[1,2,3,4,5] 

Haskell 中的列表是同质的,这意味着它们不允许您声明不同类型数据的列表。任何像 [1,2,3,4,5,a,b,c,d,e,f] 这样的列表都会产生错误。

Prelude> [1,2,3,4,5,a,b,c,d,e,f] 

这段代码将产生以下错误:

<interactive>:17:12: Not in scope: 'a' 
<interactive>:17:14: Not in scope: 'b' 
<interactive>:17:16: Not in scope: 'c' 
<interactive>:17:18: Not in scope: 'd' 
<interactive>:17:20: Not in scope: 'e' 
<interactive>:17:22: Not in scope: 'f'

列表推导

列表推导是使用数学表达式生成列表的过程。让我们来看下面的例子,在这个例子中,我们使用 [output | range ,condition] 格式的数学表达式生成列表。

Prelude> [x*2| x<-[1..10]] 
[2,4,6,8,10,12,14,16,18,20]  
Prelude> [x*2| x<-[1..5]] 
[2,4,6,8,10]  
Prelude> [x| x<-[1..5]] 
[1,2,3,4,5]

这种使用数学表达式创建列表的方法称为列表推导

元组

Haskell 提供了另一种方法来在一个数据类型中声明多个值。这被称为元组。元组可以被认为是列表,但是元组和列表之间存在一些技术差异。

元组是不可变的数据类型,我们不能在运行时修改元素的数量,而列表是可变的数据类型。

另一方面,列表是同质的数据类型,而元组是异质的,因为元组可能包含不同类型的数据。

元组由单个括号表示。让我们来看下面的例子,看看 Haskell 如何处理元组。

Prelude> (1,1,'a') 

它将产生以下输出:

(1,1,'a') 

在上面的例子中,我们使用了一个包含两个数字类型变量和一个字符类型变量的元组。

广告