\( \newcommand\D{\mathrm{d}} \newcommand\E{\mathrm{e}} \newcommand\I{\mathrm{i}} \newcommand\bigOh{\mathcal{O}} \newcommand{\cat}[1]{\mathbf{#1}} \newcommand\curl{\vec{\nabla}\times} \newcommand{\CC}{\mathbb{C}} \newcommand{\NN}{\mathbb{N}} \newcommand{\QQ}{\mathbb{Q}} \newcommand{\RR}{\mathbb{R}} \newcommand{\ZZ}{\mathbb{Z}} \)
UP | HOME

Input/Output in SML

Table of Contents

1. Introduction/Overview

I'm curious about the implementation details of input/output in Haskell and Standard ML, specifically how they compare to each other.

The Standard ML input/output seems to be specified in the Standard Basis library.

1.1. Observation

There seems to be no adequate way to formally specify input/output. Consequently, this is the only source of impurity which does not appear in the formal definition of Standard ML.

I also do not believe there is any adequate way to reason about IO.

2. Haskell

Haskell's IO Monad works with an abstraction called "handles". They are defined as (stripping back to bare bones):

data Handle
  = FileHandle FilePath !(MVar Handle__)
  | DuplexHandle FilePath !(MVar Handle__) !(MVar Handle__)

data Handle__ = Handle__ {
    haFD :: !FD
    haType :: HandleType
    haIsBin :: Bool
    haIsStream :: Bool
    haBufferMode :: BufferMode
    haBuffer :: !(IORef Buffer)
    haBuffers :: !(IORef BufferList)
    haOtherSide :: (Maybe (MVar Handle__))
}

Then openFile :: FilePath -> IOMode -> IO Handle creates a new IO monad wrapping around any IO computations involving the given file.

Roughly, a Handle is approximately equivalent to a union of a Reader and Writer in Standard ML. Instead of file descriptors, Standard ML uses OS.IO.iodesc for a platform-independent way to describe "files". Then Haskell's IO roughly corresponds to the TextIO module in Standard ML, but in a monadic fashion.

Last Updated 2023-02-20 Mon 08:02.