Michael Pankov
Michael Pankov

Reputation: 3701

Why does my instance of Random behave incorrectly?

I have the following source

-- 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)

When I do ghci Quantity.hs and then

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

the output of last step is

Quantity <no newline>

and the computation apparently hangs, but the CPU doesn't do anything (confirmed via System Monitor).

At the same time

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

works and outputs

Quantity 2092838931

What is the problem?

Upvotes: 2

Views: 179

Answers (1)

Jan Christiansen
Jan Christiansen

Reputation: 3173

In Haskell, the order of the definitions of a let expression does not matter. That is, the expression

let x = 1
    y = x + 1
in
y

evaluates to 2 as well as the following expression.

let y = x + 1
    x = 1
in
y

As a consequence, on the right-hand side of a definition all other definitions are visible and hide variables with the same name. That is, in your definition

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

the g defined in the second definition of the let hides the argument of random. Therefore, the definition of g is recursive and its evaluation does not terminate.

Upvotes: 12

Related Questions