Mengapa Haskell's Prelude.read tidak mengembalikan Maybe?

108

Apakah ada alasan bagus mengapa tipe Prelude.read itu

read :: Read a => String -> a

daripada mengembalikan Maybenilai?

read :: Read a => String -> Maybe a

Karena string mungkin gagal diuraikan Haskell, bukankah yang terakhir lebih natural?

Atau bahkan Either String a, di mana Leftakan berisi string asli jika tidak diurai, dan Righthasilnya jika demikian?

Edit:

Saya tidak mencoba membuat orang lain menulis bungkus yang sesuai untuk saya. Hanya mencari kepastian bahwa melakukannya aman.

Bilal Barakat
sumber
14
Mengapa tidak takemenerimanya Num a => a? Mengapa ada kasus khusus fmapuntuk daftar? Mengapa Functortidak diperlukan untuk Monadcontoh? Saya berharap jawabannya serupa dengan jawaban atas pertanyaan ini dan pertanyaan terkait.
3
Nah, itulah mengapa saya mengutarakannya seperti yang saya lakukan, membiarkan opsi terbuka bahwa tidak ada alasan bagus. Meskipun saya juga menduga mungkin tidak ada, seperti untuk contoh terkenal yang Anda berikan, ada baiknya meminta untuk memastikan bahwa menulis bungkus saya sendiri tidak akan menimbulkan masalah yang tidak terduga di hilir.
Bilal Barakat
Saya berharap suatu readMaybefungsi akan segera ditambahkan.
Agustus
Poin yang baik @delnan, tetapi seharusnya tidak takemenjadi Integral n => n -> [a] -> [a]?
Doug McClean
@DougMcClean: Ya, seharusnya Integral, bukan Num- otak kentut.

Jawaban:

106

Edit : Mulai GHC 7.6, readMaybetersedia di Text.Readmodul dalam paket dasar, bersama dengan readEither: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Text-Read.html#v: readMaybe


Pertanyaan bagus! Jenis pembacaan itu sendiri tidak berubah dalam waktu dekat karena itu akan merusak banyak hal. Namun, harus ada maybeReadfungsi.

Kenapa tidak ada? Jawabannya adalah "inersia". Ada sebuah diskusi di tahun '08 yang digagalkan oleh diskusi tentang "gagal."

Kabar baiknya adalah bahwa orang-orang cukup yakin untuk mulai menjauh dari kegagalan di perpustakaan. Kabar buruknya adalah bahwa lamaran itu hilang dalam pengacakan. Ada harus menjadi fungsi seperti, meskipun satu mudah untuk menulis (dan ada zillions versi sangat mirip mengambang sekitar banyak codebases).

Lihat juga pembahasan ini .

Secara pribadi, saya menggunakan versi dari paket aman .

sclv
sumber
30

Ya, ini akan berguna dengan fungsi baca yang mengembalikan Maybe. Anda dapat membuatnya sendiri:

readMaybe :: (Read a) => String -> Maybe a
readMaybe s = case reads s of
              [(x, "")] -> Just x
              _ -> Nothing
agustus
sumber
3
Terima kasih! Saya harap hasil editnya tidak terdengar tidak bersyukur! :) Hanya ingin memperjelas saya tidak bertanya karena malas ...
Bilal Barakat
6
Jika @augustss tidak dapat menyediakannya, jawaban yang lebih baik mungkin tidak ada.
John L
2
Saya tidak berpikir versi mungkin pernah dibahas dalam desain aslinya. Banyak dari hal-hal ini menjadi jelas dengan pengalaman, tetapi sulit untuk diprediksi.
Agustus
The Alasan yang membaca kembali daftar adalah untuk kasus di mana ada beberapa mem-parsing valid. Kasus Maybe berada di antara membaca dan membaca.
Chris Kuklewicz
Saya pikir ini membutuhkan kelas Read atipe:readMaybe :: Read a => String -> Maybe a
David Tchepak
15

Terlepas dari kelembaman dan / atau perubahan wawasan, alasan lain mungkin karena secara estetika menyenangkan memiliki fungsi yang dapat bertindak sebagai semacam kebalikan dari show. Artinya, yang Anda inginkan read . showadalah identitas (untuk tipe yang merupakan turunan dari Showdan Read) dan itu show . readadalah identitas pada kisaran show(yaitu show . read . show == show)

Memiliki Maybetipe a readmematahkan simetri dengan show :: a -> String.

yatima2975
sumber
Terima kasih telah menambahkan sudut pandang baru! Itu masuk akal. Tetapi untuk mencapai itu dengan rapi, bukankah masuk akal jika acara dan baca menghasilkan tipe yang berbeda, katakanlah "ParseableString"?
Bilal Barakat
1
@BilalBarakat: Jenis yang berbeda bisa jadi newtype ValidShow a = ValidShow String. Tipe phantom membuatnya lebih aman untuk tipe.
yairchu
9
Ini poin yang menarik, tetapi akhirnya, simetri yang salah. Pemrogram harus menghargai kebenaran daripada estetika.
Matt Fenwick
1
@yairchu Tidak langsung jelas bagi saya apa yang Anda maksud tentang tipe hantu, jadi saya akan mengklarifikasi jika ada orang lain yang bingung seperti saya. Anda bermaksud seperti showThing :: Show a => a -> ValidShow adan readThing :: Read a => ValidShow a -> a, sehingga jenis hal yang ditampilkan diingat dalam objek ValidShow. Dengan cara ini Anda tidak bisa menulis readThing (showThing True) :: String.
amalloy
12

Seperti yang ditunjukkan @augustss, Anda dapat membuat fungsi baca aman Anda sendiri. Namun, perintahnya readMaybetidak sepenuhnya konsisten dengan read, karena tidak mengabaikan spasi di akhir string. (Saya melakukan kesalahan ini sekali, saya tidak begitu ingat konteksnya)

Melihat definisi read dalam laporan Haskell 98 , kita dapat memodifikasinya untuk mengimplementasikan readMaybeyang sangat konsisten read, dan ini tidak terlalu merepotkan karena semua fungsi yang bergantung padanya didefinisikan dalam Prelude:

readMaybe        :: (Read a) => String -> Maybe a
readMaybe s      =  case [x | (x,t) <- reads s, ("","") <- lex t] of
                         [x] -> Just x
                         _   -> Nothing
lpsmith.dll
sumber
1
Terima kasih! +1 untuk memperingatkan saya tentang masalah spasi, yang belum pernah dibuat eksplisit sebelumnya.
Bilal Barakat
3
Perhatikan bahwa jika Anda hanya menggunakan safepaket tersebut, Anda akan mendapatkan versi yang benar dari yang readMaybetersedia (disebut readMaydan identik dengan versi ini.
Neil Mitchell
8

Fungsi ini (disebut readMaybe) sekarang ada di pendahuluan Haskell! (Pada basis saat ini - 4.6)

amindfv
sumber
2
Nah, teks yang ditautkan mengatakan itu di Teks. Baca dan bukan di Prelude (Mungkin telah berubah), namun, itu masih membantu saya!
Kapichu