此代码:
y :: Int
y = y + 1
执行时会导致GHCI挂起。
y :: Int; this means y is of type Int
y = y + 1; this means y is defined to be an Int + 1
如果我对陈述的定义不正确,请纠正我。
为什么不评估?
是否正在将y添加到Int中,但它只是被添加到某个类型而不是值?
答案 0 :(得分:4)
那是因为它无限地递归。您正在调用y
,其定义为y + 1
。那么评估将如何进行呢?
它是这样的:
y
y + 1
(y + 1) + 1
((y + 1) + 1) + 1
依旧......
答案 1 :(得分:3)
更广泛地说,Haskell文件(或GHCi)不包含命令/命令列表,就像其他一些编程语言一样。它是一种不同风格的编程语言。相反,您可以访问以下几种顶级语句:
您可以定义值。 y = y + 1
将符号y
定义为函数(+)
应用于其他两个参数y
和1
。此定义在整个文件中包含,特别是上面的定义定义中的。因此,您可以在y = x + 1
文件中完整地写x = 2
然后.hs
,并向GHCi询问y
,它会说3
。请注意,使用let
关键字会变得更复杂,这会形成一个"墙"定义的这种广泛性:let
接受一个定义块和一个值表达式,并将这些定义范围限定在组合(定义块,值表达式)上下文中,但是从这些定义中除去那些定义。 let
之外的世界。所以这也是有效的:
Prelude> let y = x + 1; x = 2
Prelude> y
3
您可以定义数据结构及其构造函数。构造函数是一个特殊的函数,我们允许它参与模式匹配:换句话说,Haskell知道如何反转或 destructure 每个构造函数。您还可以定义type
同义词和newtype
,它们介于两者之间。
您可以提供有关各个值(类型声明)的元数据。这些对于缩小类型错误的位置非常有帮助,因为它们设置了一个" wall"对于类型推断算法。它们还可以在添加多态性(Haskell具有"单态限制"经常咬新手)或将多态性限制为具体类型时具有语义效果。
您可以提供有关整个软件包的元数据:它如何包含其他软件包(import语句)以及其他软件包如何使用它们(模块语句)。
这些都不是你给Haskell系统的订单;相反,您的文件是模块的所有大描述。类似地,在表达式(上面的第一部分)中,您只能做一些事情,而且它们通常不是必需的:您可以将值应用于其他值,创建函数,您可以创建本地定义(let
)和模式匹配(case
),您可以在本地添加类型元数据。其他所有内容,包括do
符号,只是一种更方便的方法("语法糖")来完成上述事情。
你的两个语句是一个类型声明("这个模块定义的y
的类型将是一个整数")和一个定义("来计算{{1根据此模块的定义,首先计算y
的值,然后向其中添加一个")。 Haskell一起读取它们并且说,"哦,y
具有类型y
,所以Int
是我所知道的特定Int-Plus操作,(+)
,然后(+) :: Int -> Int -> Int
是我知道的那个名字的具体1
。然后它将确认类型是自洽的,并产生一些永远循环的命令性代码。