Конкретной реализации для IO
не существует;это абстрактный тип, точная реализация которого не определена в отчете Haskell.В самом деле, ничто не мешает реализации, реализующей IO
и ее экземпляр Monad
в качестве примитивов компилятора, вообще без реализации на Haskell.
По сути, Monad
используется как интерфейс до IO
, что само по себе не может быть реализовано в чистом Haskell.Это, вероятно, все, что вам нужно знать на этом этапе, и погружение в детали реализации, скорее всего, приведет к путанице, а не к пониманию.представляет IO a
как функцию, похожую на State# RealWorld -> (# State# RealWorld, a #)
(в качестве возвращаемого типа используется распакованный кортеж ), но это вводит в заблуждение;это деталь реализации, и эти значения State# RealWorld
на самом деле не существуют во время выполнения.IO
is не монада состояний, 1 в теории или на практике.
Вместо этого GHC использует нечистые примитивы для реализации этих операций ввода-выводаоперации;State# RealWorld
«значения» служат только для остановки операторов переупорядочения компилятора путем введения зависимостей данных от одного оператора к другому.
Но если вы действительно хотите увидеть реализацию GHC return
и (>>=)
,вот они:
returnIO :: a -> IO a
returnIO x = IO $ \ s -> (# s, x #)
bindIO :: IO a -> (a -> IO b) -> IO b
bindIO (IO m) k = IO $ \ s -> case m s of (# new_s, a #) -> unIO (k a) new_s
, где unIO
просто разворачивает функцию из конструктора IO
.
Важно отметить, что IO a
представляет описание нечистых вычислений, которые можно запустить, чтобы получить значение типа a
.Тот факт, что есть способ получить значения из внутреннего представления GHC IO
, не означает, что это справедливо в целом, или что вы можете сделать это для всех монад.Это просто деталь реализации со стороны GHC.
1 Монада состояний - это монада, используемая для доступа и изменения состояния в серии вычислений;он представлен как s -> (a, s)
(где s
- это тип состояния), что выглядит очень похоже на тип, который GHC использует для IO
, поэтому возникает путаница.