Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - Couldn't match type [] with IO

I am new at Haskell. Why am I getting the error message

(Couldn't match type '[]' with 'IO' — Haskell) in folowing code.

In main I only need time of algorithm running without the result.

Only want to measure algorithm time.

qsort1 :: Ord a => [a] -> [a]
qsort1 []     = []
qsort1 (p:xs) = qsort1 lesser ++ [p] ++ qsort1 greater
    where
        lesser  = [ y | y <- xs, y < p ]
        greater = [ y | y <- xs, y >= p ]

main = do
    start <- getCurrentTime
    qsort1 (take 1000000 $ randomRs (1, 100000) (mkStdGen 42))
    end <- getCurrentTime
    print (diffUTCTime end start) 
like image 483
MatejKr Avatar asked Jul 17 '15 15:07

MatejKr


1 Answers

Your main function isn't right. Unless qsort1 is an IO action you cannot perform it in an IO monad. Instead you can put it in the let binding:

main = do
    start <- getCurrentTime
    let x = qsort1 (take 1000000 $ randomRs ((1 :: Int), 100000) (mkStdGen 42))
    end <- getCurrentTime
    print (diffUTCTime end start) 

Also note that I have explicitly given a type annotation for 1 to avoid some compile errors.

But that being said you cannot actually find the the total time taken to do the sorting because of lazy evaluation. x will never be computed because it's never used in the program. If you run main, it give you this output which is definetly wrong:

λ> main
0.000001s

Instead you can use this to calculate the computation:

main = do
    start <- getCurrentTime
    let x = qsort1 (take 1000000 $ randomRs ((1 :: Int), 100000) (mkStdGen 42))
    print x
    end <- getCurrentTime
    print (diffUTCTime end start)  

Instead of printing, you can also use the BangPatterns extension to force the computation of qsort1:

main = do
    start <- getCurrentTime
    let !x = qsort1 (take 1000000 $ randomRs ((1 :: Int), 100000) (mkStdGen 42))
    end <- getCurrentTime
    print (diffUTCTime end start)   

BangPatterns will not lead to full evaluation as @kosmikus points out. Instead use a library like criterion which has been specially made for benchnmarking.

like image 177
Sibi Avatar answered Oct 23 '22 19:10

Sibi