В качестве предисловия это не «IO
Monad
», несмотря на то, что говорят многие плохо написанные введения. Это просто «тип IO
». В монадах нет ничего волшебного. Класс Haskell - довольно скучная вещь - это просто незнакомый и более абстрактный, чем то, что может поддерживать большинство языков. Вы никогда не увидите, чтобы кто-нибудь звонил IO
«IO
Alternative
», хотя IO
реализует Alternative
. Сфокусировать слишком много на Monad
только на пути обучения.
Концептуальная магия для принципиальной обработки эффектов (не побочных эффектов!) В чистых языках - это наличие типа IO
. Это настоящий тип. Это не какой-то флаг, говорящий: «Это нечисто!». Это полный тип типа Haskell * -> *
, как и Maybe
или []
. Подписи типов, принимающие значения ввода-вывода в качестве аргументов, например IO a -> IO (Maybe a)
, имеют смысл. Тип подписи с вложенным IO имеет смысл, например IO (IO a)
.
Так что, если это настоящий тип, он должен иметь конкретное значение. Maybe a
как тип представляет собой возможно отсутствующее значение типа a
. [a]
означает 0 или больше значений типа a
. IO a
означает последовательность эффектов, которые производят значение типа a
.
Обратите внимание, что цель IO
состоит в том, чтобы представить последовательность эффектов. Как я сказал выше, это не побочные эффекты. Они не могут быть скрыты в безобидном виде листа программы и загадочно меняют вещи за спиной другого кода. Вместо этого эффекты довольно явно вызваны тем фактом, что они являются значением IO
. Вот почему люди пытаются свести к минимуму часть своей программы, используя типы IO
. Чем меньше вы там делаете, тем меньше возможностей для пугающего действия на расстоянии, мешающем вашей программе.
Что касается основной цели вашего вопроса, то - полная программа Haskell - это значение IO
, называемое main
, и набор определений, которые он использует. Компилятор, когда он генерирует код, вставляет явно не-Haskell блок кода, который фактически выполняет последовательность эффектов в значении IO
. В некотором смысле это то, о чем Симон Пейтон Джонс (один из давних авторов GHC) заходил в своем разговоре Haskell is useless.
Это правда, что все, что на самом деле выполняет IO-действие, не может оставаться концептуально чистым.(И есть эта очень нечистая функция, которая запускает действия IO
, выставленные на языке Haskell. Я не буду говорить об этом больше, чем она была добавлена для поддержки интерфейса внешних функций, и использование этого неправильно будет очень сильно нарушать вашу программу.) Но точка Haskell заключается в том, чтобы обеспечить принципиальный интерфейс для системы эффектов и скрыть беспринципные биты. И он делает это таким образом, который на самом деле очень полезен на практике.
(комментируя, потому что я не уверен на 100%). Я понимаю, что IO моделируется как монашеская государственная монада с «реальным миром» как государство. Компилятор/среда выполнения фактически преобразует это в операции ввода-вывода, которые реализованы с использованием привязок к API операционной системы. Чисто функциональное программирование могло бы вычислить что угодно, но никому об этом не рассказывать. Нам нужно время выполнения, которое может конвертировать эти действия с состоянием в реальном мире в реальные вызовы базовой операционной системе. – bheklilr
https://wiki.haskell.org/IO_inside#Welcome_to_the_RealWorld.2C_baby –