I have the following code:
import Data.Array
import Control.Monad
import Data.Functor
import System.Random (randomRIO)
randomList 0 = return []
randomList n = do
r <- randomRIO (1,6)
rs <- randomList (n-1)
return (r:rs)
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <- xs, a <= x]
biggerSorted = quicksort [a | a <- xs, a > x]
in smallerSorted ++ [x] ++ biggerSorted
I need to apply sorting to the created array:
quicksort (randomList 10)
, but an error occurs:
"Couldn't match expected type‘ [a] ’with actual type IO [Int]’"
You should include type signatures for all top-level names in your program. if you don't know them, load the file and ask GHCi: Main> :t randomList
. Then copy-paste it to the file (or specialize it first, as you see fit). Place the type signature above the name it describes.
GHCi says
randomList ::
(System.Random.Random t, Num t, Num a, Eq a) => a -> IO [t]
but you most probably meant
randomList :: (System.Random.Random t, Num t) => Int -> IO [t]
randomList 0 = return []
randomList n = do
r <- randomRIO (1,6) -- randomRIO (1,6) :: IO t , r :: t
rs <- randomList (n-1) -- rs :: [t]
return (r:rs) -- r :: t , rs :: [t]
In general,
randomRIO (1,6) :: (System.Random.Random a, Num a) => IO a
You cast a 6-sided die n
times and collect the results in a list. By the way the same thing is done by
sequence $ replicate n (randomRIO (1,6))
===
replicateM n (randomRIO (1,6))
> :t \n -> replicateM n (randomRIO (1,6))
:: (System.Random.Random a, Num a) => Int -> IO [a]
Then, GHCi also tells us that
quicksort :: Ord t => [t] -> [t]
But randomList n
is IO [t]
, not [t]
. To get to the [t]
value living inside the IO [t]
, you need to do it on the inside:
sortRandom :: (Ord t, Monad m) => m [t] -> m [t]
sortRandom randomlist = do
xs <- randomlist -- randomlist :: IO [t] , xs :: [t]
let ys = quicksort xs
return ys
The above can be abbreviated to
sortRandom :: (Ord t, Monad m) => m [t] -> m [t]
sortRandom = liftM quicksort -- for monads
or
sortRandom :: (Ord t, Functor f) => f [t] -> f [t]
sortRandom = fmap quicksort -- for functors
whichever you prefer. Both work with IO
which is a monad, and any monad is also a functor. So in the end you can define
foo :: Int -> IO [Int]
foo n = liftM quicksort $ replicateM n (randomRIO (1,6))