Чому доступ до System.Info не вважається операцією вводу-виводу в Haskell?


25

У модулі System.Infoя бачу такі функції:

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

Чому його там немає IO? Вони звертаються до системи ... Я помиляюся? Моє сподівання було щось на кшталт:

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

Корпус:

      print os            -- "darwin"
      print arch          -- "x86_64"
      print compilerName  -- "ghc"

Відповіді:


29

Ви не отримуєте цю інформацію під час виконання . Вони жорстко кодуються в компіляторі, як встановлено у вашій системі.

Це найбільш очевидно, якщо ви подивитесь на визначення compilerName, яке знайдено в http://hackage.haskell.org/package/base-4.12.0.0/docs/src/System.Info.html .

compilerName :: String
compilerName = "ghc"

але навіть щось подібне os

os :: String
os = HOST_OS

визначається через інакше невизначене ім'я HOST_OS(значення, що починається з великої літери ??), що говорить про те, що це просто заповнювач, який замінюється під час встановлення.

Хтось також може мене виправити (будь ласка!), Але {-# LANGUAGE CPP #-}прагма вгорі цього файлу передбачає, що HOST_OSподібний рядок замінюється відповідними рядками препроцесором C перед компіляцією.


2
Якщо ОП дійсно хоче щось IOтам, то uname(3)на Hackage доступна обгортка: hackage.haskell.org/package/bindings-uname
thsutton

19

Питання хороше. Відповідь, така, як це, полягає в тому, що ці значення є статичними для складання програми. Вони по суті складаються в програму, і ніколи не змінюються після цього. Таким чином, нічого (у припущеннях, що використовує GHC) не порушується, якщо ви ставитесь до них як до констант. І зручніше використовувати просту константну дію, ніж IO.

Але це все своєрідні міркування. Haskell - стара мова. (Ні, насправді, вона старша за Яву на кілька років.) Багато бібліотек було створено з аргументацією, яка вже не вважається найкращою практикою. Це приклади цього. Сучасна бібліотека, що відкриває їх, ймовірно, зробить їх ІО-діями, хоча результати не змінюються після компіляції. Корисніше розміщувати речі, які не є константами на рівні джерела, за діями вводу-виводу, хоча все ж є деякі помітні винятки, наприклад, Intзміна розміру між 32- та 64-бітними платформами.

У будь-якому випадку ... Я б сказав, що ваші очікування є суворими, і ці типи є результатами історичних диваків.


-9

EDIT: Дякуємо @interjay та @Antal Spector-Zabusky за пояснення, чому ця відповідь не використовується. Вони писали

Документація трохи вводить в оману. Значення жорстко кодуються в компіляторі GHC. Після 48 років ви напевно знаєте, що фактичний код завжди перевершує документацію. - interjay вчора @ andy256 Ви абсолютно праві, що документація погана (справді, це частина того, чому Франциско задав це питання в першу чергу), і ваше плутанина зрозуміла. Справа в Haskell полягає в тому, що якщо ці значення String можуть змінюватися під час виконання, це буде немилої помилкою - змінні змін не дозволяється змінювати. У цьому полягає значення конструктора типу IO - він являє собою обчислення, яким дозволено отримати доступ до «зовнішнього світу», і так, той, результат якого може змінитися. Здійснення системного виклику - хороший приклад дії IO. ... [1/2] - Antal Spector-Zabusky 9 годин тому @ andy256… (Ще одна дія IO могла б бути "оновленням глобального лічильника".) Отже, коли ми бачимо String, ми знаємо, що він не може робити жодного зв'язку з ОС під кришкою. Ось чому, можливо, дивно, якщо ви не звикли до Haskell, реалізувати os :: String для системного виклику було б непросто - будь-яке таке значення в базовому Haskell є незмінним, порушує сподівання кожного програміста на те, як програми робота, і, можливо, навіть збільшити компілятор і оптимізатор (не теоретичне питання - є відповіді на переповнення стека, коли люди стикаються з аналогічними проблемами). [2/2] - Антал Спектор-Забуський Ось чому, можливо, дивно, якщо ви не звикли до Haskell, реалізувати os :: String для системного виклику було б непросто - будь-яке таке значення в базовому Haskell є незмінним, порушує сподівання кожного програміста на те, як програми робота, і, можливо, навіть збільшити компілятор і оптимізатор (не теоретичне питання - є відповіді на переповнення стека, коли люди стикаються з аналогічними проблемами). [2/2] - Антал Спектор-Забуський Ось чому, можливо, дивно, якщо ви не звикли до Haskell, реалізувати os :: String для системного виклику було б непросто - будь-яке таке значення в базовому Haskell є незмінним, порушує сподівання кожного програміста на те, як програми робота, і, можливо, навіть збільшити компілятор і оптимізатор (не теоретичне питання - є відповіді на переповнення стека, коли люди стикаються з аналогічними проблемами). [2/2] - Антал Спектор-Забуський і, можливо, навіть відключити компілятор та оптимізатор (що не є теоретичним питанням - є відповіді на переповнення стека, коли люди стикаються з аналогічними проблемами). [2/2] - Антал Спектор-Забуський і, можливо, навіть відключити компілятор та оптимізатор (що не є теоретичним питанням - є відповіді на переповнення стека, коли люди стикаються з аналогічними проблемами). [2/2] - Антал Спектор-Забуський

Наразі це два голоси видалення. Я дозволю цьому процесу прийняти його, але припустимо, що він насправді має деяке значення. Зі сторони їх пояснення показують, що питання було слабким, а також відповіді, оскільки новачок Haskell міг легко слідувати міркуванням, які я робив.

Оригінальна відповідь:

Я не програміст Haskell, але два наведені відповіді не відповідають документації, з якою пов'язана ОП.

Моє тлумачення документації випливає.

os :: String - Це дає вам "Операційну систему, на якій працює програма".

Я очікую, що це видасть системний виклик для отримання інформації. Оскільки система, з якої складається програма, може відрізнятися від тієї, на якій вона працює, не може бути значенням, вставленим компілятором. Якщо код інтерпретується, то інтерпретатор може надати результат, який необхідно отримати через системний виклик.

arch :: String - Це дає вам "Машинна архітектура, на якій працює програма".

Знову ж таки, я очікую, що це видасть системний виклик для отримання інформації. Оскільки система, з якої складається програма, може відрізнятися від тієї, на якій вона працює, не може бути значенням, вставленим компілятором.

compilerName :: String - Це дає вам "реалізацію Haskell, з якою програма була складена або інтерпретується".

Це значення, безумовно, вставляється компілятором / інтерпретатором.

compilerVersion :: String - Це дає "Версію compilerName з якою програма була складена або інтерпретується".

Це значення, безумовно, вставляється компілятором / інтерпретатором.

Хоча ви можете вважати, що перші два дзвінки є вхідними, результат отримується від значень, що зберігаються в операційній системі. Введення / виведення, як правило, відноситься до вторинного доступу до сховища.


3
Це не вірно для haskell. Тут будь-які обчислення не є упорядкованими, і їх результат може бути кешований. Функції є чистими, тому, якщо функція не приймає аргументів, то це дуже схоже на константу. Функції одного аргументу виглядають як просто хешмапи або словники, які обчислюють значення на основі ключа. Ви не можете використовувати зовнішнє середовище, виконувати систематичні дзвінки в таких функціях, навіть не можете отримати випадкове число або поточну дату. Але якщо ви насправді хочете використовувати те "послідовне" або оточення, то вам потрібно використовувати IOмонаду для емуляції стану, емуляцію послідовності операцій
Юрій Коваленко

"Ви не можете використовувати зовнішнє середовище, виконайте системні дзвінки в таких функціях" - Звичайно, ви можете, особливо якщо "ви" є компілятором Haskell! Реалізацію Haskell було б дуже легко здійснити os :: Stringтак, щоб вона здійснювала системний виклик, коли вона оцінюється.
Tanner Swett

2
Я не думаю, що ти розумієш значення монади IO в Haskell.
Sneftel

@Sneftel Ви, звичайно, правильні. Я вирішив відповісти, оскільки після 48 років програмування в кожній парадигмі та написання непарного компілятора вихідні відповіді не відповідали документації, і вони досі не відповідають. Це чітко говорить про це osі archотримуються під час виконання.
andy256

1
Документація трохи вводить в оману. Значення жорстко кодуються в компіляторі GHC. Після 48 років ви напевно знаєте, що фактичний код завжди перевершує документацію.
interjay
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.