2

我有以下来源

-- Quantity.hs
import System.Random

data Quantity = Quantity Integer deriving (Show)

instance Random Quantity where
    randomR (Quantity lo, Quantity hi) g =
        let rand = randomR (lo, hi) g
            (r, g) = rand
        in (Quantity r, g)
    random g =
        let rand = random g
            (r, g) = rand
        in (Quantity r, g)

当我这样做ghci Quantity.hs然后

let g = mkStdGen 0
let (r, g1) = random g :: (Quantity, StdGen)
r

最后一步的输出是

Quantity <no newline>

并且计算显然挂起,但 CPU 没有做任何事情(通过系统监视器确认)。

同时

let (r, g1) = random g :: (Integer, StdGen)
Quantity r

作品和产出

Quantity 2092838931

问题是什么?

4

1 回答 1

12

在 Haskell 中,let表达式定义的顺序无关紧要。也就是说,表达式

let x = 1
    y = x + 1
in
y

计算2结果为以及以下表达式。

let y = x + 1
    x = 1
in
y

因此,在定义的右侧,所有其他定义都是可见的,并隐藏了具有相同名称的变量。也就是说,在您的定义中

random g =
  let rand = random g
      (r, g) = rand
  in (Quantity r, g)

g第二个定义中的定义let隐藏了 的参数random。因此, 的定义g是递归的,并且它的评估不会终止。

于 2013-08-11T18:15:55.813 回答