Haskell - Tidak dapat mencocokkan tipe [] dengan IO

Saya baru di Haskell. Mengapa saya menerima pesan kesalahan

(Tidak dapat mencocokkan tipe '[]' dengan 'IO' — Haskell) pada kode berikut.

Pada dasarnya saya hanya perlu waktu menjalankan algoritma tanpa hasil.

Hanya ingin mengukur waktu algoritma.

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) 

person MatejKr    schedule 17.07.2015    source sumber


Jawaban (2)


Fungsi main Anda tidak benar. Kecuali qsort1 merupakan tindakan IO Anda tidak dapat melakukannya di monad IO. Sebagai gantinya, Anda bisa memasukkannya ke dalam ikatan let:

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

Perhatikan juga bahwa saya telah secara eksplisit memberikan anotasi tipe untuk 1 untuk menghindari beberapa kesalahan kompilasi.

Namun demikian, Anda sebenarnya tidak dapat menemukan total waktu yang dibutuhkan untuk melakukan penyortiran karena evaluasi yang malas. x tidak akan pernah dihitung karena tidak pernah digunakan dalam program. Jika Anda menjalankan main, ini memberi Anda keluaran yang jelas salah:

λ> main
0.000001s

Sebagai gantinya, Anda dapat menggunakan ini untuk menghitung perhitungannya:

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

Daripada mencetak, Anda juga dapat menggunakan ekstensi BangPatterns untuk memaksa penghitungan qsort1:

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

BangPatterns tidak akan mengarah pada evaluasi penuh seperti yang ditunjukkan oleh @kosmikus. Sebagai gantinya gunakan perpustakaan seperti criterion yang khusus dibuat untuk benchmarking.

person Sibi    schedule 17.07.2015
comment
Terima kasih. Masalahnya adalah sekarang saya tidak mendapatkan waktu algoritma tetapi waktu algoritma dan waktu pencetakan. - person MatejKr; 17.07.2015
comment
@MatejKr Saya telah memperbarui jawaban untuk tidak menggunakan pencetakan dan malah memaksakan perhitungan menggunakan operator Bang. - person Sibi; 17.07.2015
comment
Mengapa saya mendapatkan pola bang ilegal (gunakan BangPattern). Saya orang baru di haskell Terima kasih - person MatejKr; 17.07.2015
comment
@MatejKr Letakkan {-#LANGUAGE BangPatterns#-} di atas file Anda. - person Sibi; 17.07.2015
comment
Pola poni di sini tidak benar. Hal ini tidak akan memaksakan evaluasi penuh, dan tidak memberikan hasil yang benar. Gunakan saja sesuatu seperti kriteria untuk melakukan benchmarking daripada mencoba menemukan kembali rodanya. - person kosmikus; 17.07.2015
comment
Bisakah kamu lebih spesifik. Saya baru mengenal Haskell dan tidak tahu bagaimana melakukannya. Terima kasih - person MatejKr; 17.07.2015
comment
@kosmikus Mengapa BangPatterns tidak mengarah pada evaluasi penuh di sini? Meskipun saya menerima kriteria itu harus digunakan untuk pembandingan. @MatejKr Ini adalah perpustakaan Haskell yang digunakan untuk Pembandingan. - person Sibi; 17.07.2015
comment
Karena pola poni umumnya tidak menimbulkan evaluasi penuh, melainkan hanya mengevaluasi bentuk normal kepala lemah. Dan qsort1 mengembalikan daftar. - person kosmikus; 17.07.2015

Saya menggunakan metode di bawah ini dan berfungsi dengan baik:

main = do
        let arr = take 1000000 $ randomRs ((1 :: Int), 10000000) (mkStdGen 59)
        defaultMain [
          bgroup "qs" [ bench "1"  $ nf quickSort arr ]
          ]
person MatejKr    schedule 28.07.2015