Why does the haskell compiler infer this type, but ghci cannot?

I am working on the following book to learn Haskell, looking in particular at the randomness chapter :

I run the following as a file three-coins.hs:

import System.Random 

threeCoins :: StdGen -> (Bool, Bool, Bool)  
threeCoins gen =   
    let (firstCoin, newGen) = random gen
        (secondCoin, newGen') = random newGen
        (thirdCoin, newGen'') = random newGen'
    in  (firstCoin, secondCoin, thirdCoin)

main = print ( threeCoins (mkStdGen 21) )

Then I execute with runhaskell three-coins.hsand get output similar to:

(True,True,True)

Now they make a point in the notes:

Please note that we did not need to do random gen :: (Bool, StdGen). This is because we have already indicated that we want the function to be logical in the type declaration. This is why Haskell can conclude that in this case we want to have a boolean value.

That's cool.

Now that I have run this in ghciwith the following code:

import System.Random 

:{
threeCoins :: StdGen -> (Bool, Bool, Bool)
threeCoins gen =
    let (firstCoin, newGen) = random gen
        (secondCoin, newGen') = random newGen
        (thirdCoin, newGen'') = random newGen'
    in  (firstCoin, secondCoin, thirdCoin)
:}

I get the following answer:

<interactive>:6:9: error:
    • Ambiguous type variable ‘t0’
      prevents the constraint ‘(Random t0)’ from being solved.
    • When checking that the inferred type
        newGen :: forall t. Random t => StdGen
      is as general as its inferred signature
        newGen :: StdGen
      In the expression:
        let
          (firstCoin, newGen) = random gen
          (secondCoin, newGen') = random newGen
          (thirdCoin, newGen'') = random newGen'
        in (firstCoin, secondCoin, thirdCoin)
      In an equation for ‘threeCoins’:
          threeCoins gen
            = let
                (firstCoin, newGen) = random gen
                (secondCoin, newGen') = random newGen
                ....
              in (firstCoin, secondCoin, thirdCoin)

. , , .

, , :

import System.Random 

:{
threeCoins :: StdGen -> (Bool, Bool, Bool)
threeCoins gen =
    let (firstCoin, newGen) = random gen :: (Bool, StdGen)
        (secondCoin, newGen') = random newGen :: (Bool, StdGen)
        (thirdCoin, newGen'') = random newGen' :: (Bool, StdGen)
    in  (firstCoin, secondCoin, thirdCoin)
:}

, :

threeCoins (mkStdGen 21) 

(True,True,True)

, . Haskell , , , ghci .

: haskell , ghci ?

+6
1

, , . - , , a length :: [a] -> Int. ( ), , , , , . , firstCoin secondCoin thirdCoin , (Bool, Bool, Bool), , Bool.

, Haskell , , Rank-2. , , GHCi, ( " " ), , GHCi.

firstCoin secondCoin thirdCoin .. , Bool: random (.. , random ). , :

threeCoins :: StdGen -> (Bool, Bool, Bool)  
threeCoins gen =   
    let firstCoin, secondCoin, thirdCoin :: Random r => r
        (firstCoin, newGen) = random gen
        (secondCoin, newGen') = random newGen
        (thirdCoin, newGen'') = random newGen'
    in  (firstCoin, secondCoin, thirdCoin)

, , ,

{-# LANGUAGE NoMonomorphismRestriction #-}

.

, . , r , random, , , - .

, , , :

import System.Random 
import Data.Random 

threeCoins :: RVar (Bool, Bool, Bool)  
threeCoins = do   
    firstCoin <- uniform False True
    secondCoin <- uniform False True
    thirdCoin <- uniform False True
    return (firstCoin, secondCoin, thirdCoin)

main = print . sampleState threeCoins $ mkStdGen 21

, firstCoin secondCoin thirdCoin , .

, , , ,

import Control.Monad (replicateM)

threeCoins :: RVar (Bool, Bool, Bool)  
threeCoins = do   
    [firstCoin,secondCoin,thirdCoin] <- replicateM 3 $ uniform False True
    return (firstCoin, secondCoin, thirdCoin)
+3

All Articles