Why ghc doesn't complain about types being rigid in the following function?
play :: (Monad m, MonadIO m, Random a) => a -> a -> m a
play r1 r2 = do
randomRIO (r1, r2)
In the above case, the m is actually IO. This code compiles. While othertimes, when I use a concrete type in a generic function, ghc complains that I am using a concrete type. Do I miss something here?
For example, if I say:
play :: (Monad m, MonadIO m, Random a) => a -> a -> m a
play r1 r2 = do
randomRIO (1, 6::Int)
This time ghc complains that I'm using a rigid type. The thing that bothers me is that IO is in a way a concrete or rigid type because it's IO and not Maybe.
Edit 1: Complete code that compiles without error:
{-# LANGUAGE ConstraintKinds #-}
module Main where
-- showing how to program in the mtl style
import Control.Monad.IO.Class
import System.Random
type Game m a = (Monad m, MonadIO m, Random a, Show a)
-- step 1
play :: (Game m a) => a -> a -> m a
play r1 r2 = do
yell "hi"
randomRIO (r1, r2)
--rollDice r1 r2
-- step 2
yell :: (MonadIO m) => String -> m ()
yell str = liftIO $ putStrLn str
-- step 3
rollDice :: (Game m a) => a -> a -> m a
rollDice a1 a2 = liftIO $ randomRIO (a1,a2)
main :: IO ()
main = putStrLn ""
-- main :: IO ()
-- main = do
-- play 1 (6::Int) >>= print
-- play 'a' 'z' >>= print
-- putStrLn "done"
Code that doesn't compile:
{-# LANGUAGE ConstraintKinds #-}
module Main where
-- showing how to program in the mtl style
import Control.Monad.IO.Class
import System.Random
type Game m a = (Monad m, MonadIO m, Random a, Show a)
-- step 1
play :: (Game m a) => a -> a -> m a
play r1 r2 = do
yell "hi"
randomIO 'a' 'z'
--rollDice r1 r2
-- step 2
yell :: (MonadIO m) => String -> m ()
yell str = liftIO $ putStrLn str
-- step 3
rollDice :: (Game m a) => a -> a -> m a
rollDice a1 a2 = liftIO $ randomRIO (a1,a2)
main :: IO ()
main = putStrLn ""
-- main :: IO ()
-- main = do
-- play 1 (6::Int) >>= print
-- play 'a' 'z' >>= print
-- putStrLn "done"
This doesn't compile:
{-# LANGUAGE ConstraintKinds #-}
module Main where
-- showing how to program in the mtl style
import Control.Monad.IO.Class
import System.Random
type Game m a = (Monad m, MonadIO m, Random a, Show a)
-- step 1
play :: (Game m a) => a -> a -> m a
play r1 r2 = do
yell "hi"
**randomRIO (1, 6::Int)**
--rollDice r1 r2
-- step 2
yell :: (MonadIO m) => String -> m ()
yell str = liftIO $ putStrLn str
-- step 3
rollDice :: (Game m a) => a -> a -> m a
rollDice a1 a2 = liftIO $ randomRIO (a1,a2)
main :: IO ()
main = putStrLn ""
-- main :: IO ()
-- main = do
-- play 1 (6::Int) >>= print
-- play 'a' 'z' >>= print
-- putStrLn "done"
Update
Just realized that my confusion comes from reading the wrong documentation of random
I was reading the random-1.1 documentation while using the random-1.2 in my code.
For people's reference:
random-1.1
randomRIO :: (a, a) -> IO a
random-1.2
randomRIO :: (Random a, MonadIO m) => (a, a) -> m a