Mengapa mengakses System.Info tidak dianggap sebagai operasi IO di Haskell?

25

Dalam modul System.Infosaya melihat fungsi-fungsi ini:

os :: String
arch :: String
compilerName :: String
compilerVersion :: Version

Mengapa tidak IOada? Mereka mengakses sistem ... Apakah saya salah? Harapan saya adalah sesuatu seperti:

os :: IO String
arch :: IO String
compilerName :: IO String
compilerVersion :: IO Version

Gunakan kasus:

      print os            -- "darwin"
      print arch          -- "x86_64"
      print compilerName  -- "ghc"
Francisco Albert
sumber

Jawaban:

29

Anda tidak mendapatkan informasi itu saat runtime . Mereka dikodekan dalam kompiler sebagaimana diinstal pada sistem Anda.

Ini paling jelas jika Anda melihat definisi untuk compilerNameseperti yang ditemukan di http://hackage.haskell.org/package/base-4.12.0.0/docs/src/System.Info.html .

compilerName :: String
compilerName = "ghc"

tetapi bahkan sesuatu seperti os

os :: String
os = HOST_OS

didefinisikan dalam hal nama yang tidak ditentukan HOST_OS(nilai dimulai dengan huruf besar ??) yang menunjukkan bahwa hanya placeholder yang akan diganti selama instalasi.

Seseorang juga dapat mengoreksi saya (tolong!), Tetapi {-# LANGUAGE CPP #-}pragma di bagian atas file menyarankan bahwa HOST_OSdan sejenisnya diganti oleh string yang sesuai oleh prepro C sebelum kompilasi.

chepner
sumber
2
Jika OP benar-benar ingin ada IOdi sana, ada pembungkus uname(3)tersedia di Hackage: hackage.haskell.org/package/bindings-uname
thsutton
19

Pertanyaannya bagus. Jawabannya, seperti itu, adalah bahwa nilai-nilai itu statis per kompilasi program. Mereka pada dasarnya dikompilasi ke dalam program, dan tidak pernah berubah setelah itu. Dengan demikian, tidak ada (dalam asumsi yang digunakan GHC) rusak jika Anda memperlakukannya sebagai konstanta. Dan lebih mudah menggunakan konstanta sederhana daripada aksi IO.

Tapi itu semua semacam alasan warisan. Haskell adalah bahasa kuno. (Tidak juga, ini lebih tua dari Jawa beberapa tahun). Banyak perpustakaan telah dibangun dengan alasan yang tidak lagi dianggap praktik terbaik. Ini adalah contohnya. Sebuah perpustakaan modern yang mengeksposnya mungkin akan membuat mereka bertindak IO meskipun hasilnya tidak berubah setelah kompilasi. Lebih berguna untuk meletakkan hal-hal yang bukan konstanta di tingkat sumber di belakang tindakan IO, meskipun masih ada beberapa pengecualian penting, seperti Intmengubah ukuran antara platform 32-dan 64-bit.

Dalam hal apapun ... Saya akan mengatakan harapan Anda solid, dan tipe-tipe itu adalah hasil dari keanehan sejarah.

Carl
sumber
-9

EDIT: Terima kasih kepada @interjay dan @Antal Spector-Zabusky karena telah menjelaskan mengapa jawaban ini diturunkan. Mereka menulis

Dokumentasinya agak menyesatkan. Nilai-nilai tersebut di-hardcode ke dalam kompiler GHC. Setelah 48 tahun Anda pasti tahu bahwa kode aktual selalu mengalahkan dokumentasi. - interjay kemarin @ andy256 Anda memang benar bahwa dokumentasinya buruk (memang, itulah sebabnya mengapa Francisco mengajukan pertanyaan ini sejak awal), dan kebingungan Anda dapat dimengerti. Hal tentang Haskell adalah jika nilai-nilai String tersebut dapat bervariasi pada saat runtime, itu akan menjadi bug yang mengerikan - variabel tidak diizinkan untuk berubah. Ini adalah signifikansi dari konstruktor tipe IO - ini merupakan perhitungan yang diizinkan untuk mengakses "dunia luar", dan karenanya hasilnya dapat berubah. Membuat panggilan sistem adalah contoh yang baik dari tindakan IO. ... [1/2] - Antal Spector-Zabusky 9 jam yang lalu @ andy256 ... (Tindakan IO lainnya bisa jadi "memperbarui penghitung global".) Jadi ketika kita melihat sebuah String, kita tahu bahwa itu tidak dapat melakukan komunikasi dengan OS di bawah tenda. Inilah sebabnya, mungkin secara mengejutkan jika Anda tidak terbiasa dengan Haskell, tidak akan mudah untuk mengimplementasikan os :: String untuk melakukan panggilan sistem - nilai apa pun yang tidak dapat diterapkan di Haskell dasar, akan melanggar harapan setiap programmer tentang cara program bekerja, dan bahkan berpotensi meningkatkan kompiler dan pengoptimal (bukan masalah teoretis - ada jawaban Stack Overflow di mana orang mengalami masalah analog). [2/2] - Antal Spector-Zabusky Inilah sebabnya, mungkin secara mengejutkan jika Anda tidak terbiasa dengan Haskell, tidak akan mudah untuk mengimplementasikan os :: String untuk melakukan panggilan sistem - nilai apa pun yang tidak dapat diterapkan di Haskell dasar, akan melanggar harapan setiap programmer tentang cara program bekerja, dan bahkan berpotensi meningkatkan kompiler dan pengoptimal (bukan masalah teoretis - ada jawaban Stack Overflow di mana orang mengalami masalah analog). [2/2] - Antal Spector-Zabusky Inilah sebabnya, mungkin secara mengejutkan jika Anda tidak terbiasa dengan Haskell, tidak akan mudah untuk mengimplementasikan os :: String untuk melakukan panggilan sistem - nilai apa pun yang tidak dapat diterapkan di Haskell dasar, akan melanggar harapan setiap programmer tentang cara program bekerja, dan bahkan berpotensi meningkatkan kompiler dan pengoptimal (bukan masalah teoretis - ada jawaban Stack Overflow di mana orang mengalami masalah analog). [2/2] - Antal Spector-Zabusky dan bahkan berpotensi meningkatkan kompilator dan pengoptimal (bukan masalah teoretis - ada jawaban Stack Overflow di mana orang mengalami masalah analog). [2/2] - Antal Spector-Zabusky dan bahkan berpotensi meningkatkan kompilator dan pengoptimal (bukan masalah teoretis - ada jawaban Stack Overflow di mana orang mengalami masalah analog). [2/2] - Antal Spector-Zabusky

Saat ini memiliki dua penghapusan suara. Saya akan membiarkan proses itu mengambil jalannya saja, tetapi menyarankan itu sebenarnya memiliki beberapa nilai. Di samping catatan, penjelasan mereka menunjukkan bahwa pertanyaan itu lemah, dan begitu pula jawabannya, karena seorang pemula Haskell dapat dengan mudah mengikuti alasan yang saya lakukan.

Jawaban asli:

Saya bukan programmer Haskell, tetapi dua jawaban yang sudah diberikan tidak cocok dengan dokumentasi yang ditautkan oleh OP.

Interpretasi saya terhadap dokumentasi berikut.

os :: String - Ini memberi Anda "Sistem operasi tempat program berjalan."

Saya berharap ini akan mengeluarkan panggilan sistem untuk mendapatkan informasi. Karena sistem, program yang dikompilasi mungkin berbeda dengan yang dijalankannya tidak dapat berupa nilai yang dimasukkan oleh kompiler. Jika kode ditafsirkan maka penerjemah dapat memberikan hasil, yang harus diperoleh melalui panggilan sistem.

arch :: String - Ini memberi Anda "Arsitektur mesin tempat program berjalan."

Sekali lagi, saya berharap ini akan mengeluarkan panggilan sistem untuk mendapatkan informasi. Karena sistem, program yang dikompilasi mungkin berbeda dengan yang dijalankannya tidak dapat berupa nilai yang dimasukkan oleh kompiler.

compilerName :: String - Ini memberi Anda "Implementasi Haskell dengan mana program ini disusun atau sedang ditafsirkan."

Nilai ini tentu saja dimasukkan oleh kompiler / interpreter.

compilerVersion :: String- Ini memberi Anda "Versi compilerNameprogram yang dikompilasi atau sedang ditafsirkan."

Nilai ini tentu saja dimasukkan oleh kompiler / interpreter.

Meskipun Anda dapat mempertimbangkan dua panggilan pertama untuk mendapatkan input, hasilnya berasal dari nilai yang dipegang oleh Sistem Operasi. I / O umumnya mengacu pada akses penyimpanan sekunder.

andy256
sumber
3
Itu tidak benar untuk haskell. Di sini perhitungan apa pun tidak teratur dan hasilnya dapat di-cache. Fungsinya murni, jadi jika suatu fungsi tidak menerima argumen, maka itu seperti konstanta. Fungsi dari satu arg terlihat seperti hanya hashmaps atau kamus, yang menghitung nilai berdasarkan kunci. Anda tidak dapat menggunakan lingkungan eksternal, melakukan syscalls dalam fungsi seperti itu, Anda bahkan tidak bisa mendapatkan nomor acak atau tanggal saat ini. Tetapi jika Anda benar-benar ingin menggunakan "sekuensing" itu, atau lingkungan, maka Anda perlu menggunakan IOmonad untuk meniru negara, meniru urutan operasi
Yuri Kovalenko
"Anda tidak dapat menggunakan lingkungan eksternal, lakukan syscall dalam fungsi seperti itu" - Tentu Anda bisa, terutama jika "Anda" adalah kompiler Haskell! Akan sangat mudah bagi implementasi Haskell untuk diimplementasikan os :: Stringsehingga melakukan panggilan sistem saat dievaluasi.
Tanner Swett
2
Saya tidak berpikir Anda mengerti pentingnya IO monad di Haskell.
Sneftel
@Sneftel Anda, tentu saja, benar. Saya memilih untuk menjawab karena setelah 48 tahun pemrograman dalam setiap paradigma, dan menulis kompiler aneh, jawaban awal tidak cocok dengan dokumentasi, dan mereka masih belum. Jelas mengatakan itu osdan archdiperoleh saat runtime.
andy256
1
Dokumentasinya agak menyesatkan. Nilai-nilai tersebut di-hardcode ke dalam kompiler GHC. Setelah 48 tahun Anda pasti tahu bahwa kode aktual selalu mengalahkan dokumentasi.
interjay