Difference between revisions of "The I/O problem"

From HaskellWiki
Jump to navigation Jump to search
m (Section rewritten, including added quote)
m
(47 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Functional languages are entirely mathematical, so the places where they don't work show where computing is not mathematics and help to illuminate both fields.
Haskell uses the seriously complex machinery of monads to do I/O, supposedly without side effects (I don't accept this). And you end up writing stuff [...] which to me looks like C. There must be a more functional approach.
 
   
  +
<tt>[http://www.bitsavers.org/pdf/xerox/parc/techReports/CSL-81-11_Real_Programming_in_Functional_Languages.pdf Real Programming in Functional Languages], James H. Morris (page 33 of 36).</tt>
<tt>[https://billwadge.wordpress.com/2021/05/22/monads-schmonads-functional-input-without-tears-pyfl Monads Schmonads: Functional Input without tears (PyFL)], Bill Wadge.</tt><!-- 2021 -->
 
 
</div>
 
</div>
  +
<br>
 
  +
One of those places is I/O:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
How the initial [lambda term] is input, and how the final one is output, are questions neither asked or answered.
[...] In the [http://conal.net/blog/posts/the-c-language-is-purely-functional pure functional] languages, Haskell and Clean, at present the most developed ones, the I/O problem is solved by respectively monads and uniqueness typing. But using these features, in both cases it is still possible to write incomprehensible code when dealing with I/O.
 
   
<tt>[https://lmcs.episciences.org/6755/pdf Gems of Corrado Böhm], Henk Barendregt.</tt><!-- 2020 -->
+
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.3579&rep=rep1&type=pdf How to Declare an Imperative], Philip Wadler (page 2 of 33).</tt><!-- 1997 -->
 
</div>
 
</div>
  +
<sup> </sup>
<br>
 
   
  +
== The problem is mathematical in origin ==
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
Fundamentally, all functional languages are translated to an imperative language, and it leaks.
 
   
  +
The various fields of study collectively referred to as <i>mathematics</i> are abstract in one or more ways:
It leaks when you need to read and write files, when you need to respond to real-time user events, when you write to the screen or interact with the GPU, or when you communicate with an external process or API.
 
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
<tt>[https://myowenopinion.com/post/dev/functional-programming-is-a-leaky-abstraction Functional Programming Is a Leaky Abstraction], Owen Merkling.</tt>
 
  +
In a preliminary sense, mathematics is abstract because it is studied using highly general and formal resources.
<!-- 2020 -->
 
  +
  +
<tt>[https://iep.utm.edu/math-app The Applicability of Mathematics], from the [https://iep.utm.edu/ Internet Encyclopedia of Philosophy].</tt>
 
</div>
 
</div>
  +
<br>
 
  +
In particular, they abstract away from the presence of an outside environment. For a declarative programming language like Haskell, which is based on one of these individual fields of study - higher-order functions - this raises the question of I/O and its observable effects:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
How must interactions between a program and an external environment (consisting of, e.g., input/output-devices, file systems, ...) be described in a programming language that abstracts from the existence of an outside world?
This is hard stuff. Two years ago I spent several hours to write 3 lines invoking IO computations.
 
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.9846&rep=rep1&type=pdf Functions, Frames and Interactions], Claus Reinke (page 10 of 210).</tt>
<tt>[https://discourse.haskell.org/t/trying-to-understand-the-io/1172/8 Trying to understand the <code>IO ()</code>], ''"belka"''.</tt><!-- 2020 -->
 
 
</div>
 
</div>
  +
<br>
 
  +
It should then be of little surprise that attempts to find a <i>satisfactory</i> mathematical solution for I/O have been less than successful:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
During the 1960s, several researchers began work on proving things about programs. [...]
[...] Essentially, the Haskell type <code>IO t</code> combines both the features of [Idealised Algol's] <code>comm</code> and <code>exp</code>. This makes the [Haskell] framework slightly simpler, but it can be cumbersome if imperative computations are performed extensively. [...]
 
   
  +
Several difficult problems emerged from this work. One was the problem of <i>specification</i>: before one can prove that a program is correct, one must specify the meaning of "correct", formally and unambiguously. Formal systems for specifying the meaning of a program were developed, and they looked suspiciously like programming languages.
<tt>[https://www.cs.bham.ac.uk/~udr/popl/09-17-Algol-like.pdf Handout 9: Imperative programs and the Lambda Calculus], Uday Reddy.</tt><!-- 2018 -->
 
  +
  +
Researchers began to analyze why it is often harder to prove things about programs written in traditional languages than it is to prove theorems about mathematics. Two aspects of traditional languages emerged as sources of trouble because they are very difficult to model in a mathematical system: mutability and sequencing.
  +
  +
<tt> [https://core.ac.uk/download/pdf/214330064.pdf The Anatomy of Programming Languages], Alice E. Fischer and Frances S. Grodzinsky (page 353 of 600).</tt>
 
</div>
 
</div>
<br>
 
   
  +
* mutability:
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
  +
:{|
[...] I like the concise way of coding pure functions in Haskell using mathematical ideas like recursion and list comprehensions. However, user interactions are quite painful to implement using the I/O monad. [...]
 
  +
|<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
There is <i>in principle</i> nothing to stop functional programs from passing a single extra parameter into and out of every single function in the entire system. If this extra parameter were a collection (compound value) of some kind then it could be used to <i>simulate</i> an arbitrarily large set of mutable variables. In effect this approach recreates a single pool of global variables - hence, even though referential transparency is maintained, ease of reasoning is lost (we still know that each function is dependent only upon its arguments, but one of them has become so large <i>and contains irrelevant values</i> that the benefit of this knowledge as an aid to understanding is almost nothing).
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.93.8928&rep=rep1&type=pdf Out of the Tar Pit], Ben Moseley and Peter Marks (page 17 of 66).</tt>
<tt>[https://www.linkedin.com/pulse/definition-functional-programming-rainer-grimm The Definition of Functional Programming], Dirk Verlinden.</tt><!-- 2017 -->
 
 
</div>
 
</div>
  +
|}
<br>
 
   
  +
* sequencing:
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
  +
:{|
<code>IO</code> is indeed a monad instance, but not a very nice one - the compiler treats it specially, and it is not very nice to reason about [...]
 
  +
|<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
We have experimented for some time with a means for the programmer to specify a ‘syntactic’ partial order between subexpressions, with the intended effect that the ‘semantic’ order in which the input actions occur during the evaluation is not in conflict with the specified ‘syntactic’ partial order on the subexpressions (which carries over to the input actions evoked by those subexpressions). As a consequence, whenever the evaluator is about to execute an input action, it first has to decide whether there will occur in the future another input action that should be done first according to the specified ‘syntactic’ partial order. That problem, however, is undecidable.
   
  +
<tt>[https://maartenfokkinga.github.io/utwente/mmf2001c.pdf An alternative approach to I/O], Maarten Fokkinga and Jan Kuper (page 6 of 12).</tt>
<tt>[https://nickhu.co.uk/Monads.pdf Understanding Monads], Nick Hu.</tt><!-- 2016 -->
 
 
</div>
 
</div>
  +
|}
<br>
 
  +
  +
So where to from here?
  +
  +
* What would be ideal is an extension of one or more fields of mathematics which can [https://www.cs.kent.ac.uk/people/staff/dat/krc/paraffins-turner.pdf elegantly] describe interactions with external environments - the appropriate denotational semantics can then be used to map it into languages like Haskell.
  +
  +
* Alternately (and less ideally), if it can be proven that one cannot exist (like the solution to the halting problem) then implementors everywhere can just select the most-suitable model of I/O, as they see fit.
  +
  +
== An axiomatic approach ==
  +
  +
The dependently-typed language Agda relies on Haskell for its outside interactions:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
'''4 Compiling Agda programs'''
Haskell compromises brilliantly, by fencing off pure and impure functions from one another [...] The illusion is so good that programmers are fooled into thinking I/O is pure in Haskell. And now that we can write mostly pure code with occasional impure wrappers, researchers have mostly stopped seeking superior alternatives.
 
   
  +
This section deals with the topic of getting Agda programs to interact
<tt>[https://crypto.stanford.edu/~blynn/haskell/io.html A Problem With I/O], Ben Lynn.</tt><!-- 2016 -->
 
  +
with the real world. Type checking Agda programs requires evaluating
  +
arbitrary terms, ans as long as all terms are pure and normalizing this is
  +
not a problem, but what happens when we introduce side effects? Clearly,
  +
we don't want side effects to happen at compile time. Another question is
  +
what primitives the language should provide for constructing side effecing
  +
programs. In Agda, these problems are solved by allowing arbitrary
  +
Haskell functions to be imported as axioms. At compile time, these imported
  +
functions have no reduction behaviour, only at run time is the
  +
Haskell function executed.
  +
  +
<tt>[http://www.cse.chalmers.se/~ulfn/papers/afp08/tutorial.pdf Dependently Typed Programming in Agda], Ulf Norell and James Chapman (page 38 of 41).</tt>
 
</div>
 
</div>
  +
<br>
 
  +
Haskell's FFI also allows for arbitrary foreign code to be imported, to only be executed at run time:
  +
  +
<haskell>
  +
instance Monad IO where
  +
return = unitIO
  +
(>>=) = bindIO
  +
  +
foreign import ccall "primUnitIO" unitIO :: a -> IO a
  +
foreign import ccall "primBindIO" bindIO :: IO a -> (a -> IO b) -> IO b
  +
  +
</haskell>
  +
  +
However, Haskell 2010 doesn't allow higher-order FFI declarations, or their use of type variables. Visible implementations of monadic I/O [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.3579&rep=rep1&type=pdf based on other interfaces] are another option, but Haskell 2010 also imposes restrictions on its I/O type:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
The <code>IO</code> type serves as a tag for operations (actions) that interact with the outside world. The <code>IO</code> type is abstract: no constructors are visible to the user.
[...] you shouldn't spend much time writing <code>IO</code> stuff, because it's a bad language embedded in a good one.
 
   
  +
<tt>[https://www.haskell.org/definition/haskell2010.pdf The Haskell 2010 Report] (page 95 of 329).</tt>
<tt>[https://web.archive.org/web/20220309052143/http://comonad.com/reader/2015/on-the-unsafety-of-interleaved-io On the unsafety of interleaved I/O], Dan Doel.</tt><!-- 2015 -->
 
 
</div>
 
</div>
  +
<br>
 
  +
== On being denotative ==
  +
  +
Instead of just being declarative, there have been calls for languages like Haskell to be [[Denotative|denotative]]:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
My vision of “solving the I/O problem” for functional programming is nothing
IO in Haskell [is] for me a source of great displeasure and it just defeated every try I have given to learn the language.
 
  +
like Haskell’s semantically imperative (non-)solution (called <code>IO</code>
  +
in Haskell), but rather to continue shifting semantically imperative mechanisms
  +
out of the programming model and into the implementation of (semantically simple)
  +
function application.
   
  +
<tt>[http://conal.net/blog/posts/can-functional-programming-be-liberated-from-the-von-neumann-paradigm Can functional programming be liberated from the von Neumann paradigm?], Conal Elliott.</tt>
<tt>[https://www.haskellforall.com/2013/01/introduction-to-haskell-io.html?showComment=1361296801442#c794624017122358881 Introduction to Haskell <code>IO</code>], Ludovic Kuty.</tt><!-- 2013 -->
 
 
</div>
 
</div>
  +
<br>
 
  +
As a result of that semantic simplicity:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
A functional program transforms data into other data according to a certain
Stream transformers are fragile to use, continuations are powerful but somewhat clutter the syntax of functions. Monads and uniqueness types both present a trade-off, do we accept the over-sequentialisation imposed by monads, or the visual disorder of explicit environment passing? We believe that a compromise is still to be found [...]
 
  +
algorithm. Functional programs cannot deal with input/output, cannot switch on and
  +
off lamps depending on the value of a certain parameter; in general they cannot deal
  +
with <i>process control</i>.
  +
<br>
  +
<br>
  +
These points are sometimes held as arguments against functional
  +
programming. However a reduction machine [specifically designed for the
  +
execution of functional languages] can produce <i>code</i> for process control,
  +
code that is executed by some interface. A von Neumann computer also needs
  +
interfaces for I/O and other controls. Therefore, a reduction machine with environment
  +
will consist of a pure reduction machine (dealing with algorithms that transform data)
  +
together with interfaces for process control (like I/O), see Fig. 1.
   
  +
<tt>[https://repository.ubn.ru.nl/bitstream/handle/2066/17230/13246.pdf Functional Programming and Lambda Calculus], Henk Barendregt (pages 324-325).</tt>
<tt>[https://www.owenstephens.co.uk/assets/static/research/masters_report.pdf Approaches to Functional I/O], Owen Stephens.</tt><!-- 2011 -->
 
 
</div>
 
</div>
  +
<br>
 
  +
...an environment?
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
The purely functional reduction machine is attached to a von Neumann host machine and an
Once you’re in the IO monad, you’re stuck there forever, and are reduced to Algol-style imperative programming. You cannot easily convert between functional and monadic style without a radical restructuring of code.
 
  +
imperative environment deals with I/O and interactive programs.
   
  +
<tt>[https://repository.ubn.ru.nl/bitstream/handle/2066/17283/1/13352.pdf Functional programming and the language TALE], Henk Barendregt and Marc van Leeuwen (page 126).</tt>
<tt>[https://existentialtype.wordpress.com/2011/05/01/of-course-ml-has-monads Of Course ML Has Monads!], Robert Harper.</tt><!-- 2011 -->
 
 
</div>
 
</div>
  +
<br>
 
  +
This vision of <i>“solving the I/O problem”</i> was a <s><i>“standard”</i></s> common solution in the past:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Research is [still] being done to find other solutions.
Functional programmers used to worry about how to solve “the I/O problem”. Functional programming (FP) eschews any notion of side-effect or order of ''execution'', and instead has an order-independent notion of ''evaluation''. In contrast, input & output (I/O) seems to be an inherently effectful, ordered notion.
 
  +
</div>
   
  +
=== Using more than one language ===
[...]
 
   
  +
One suggestion is to ease the relocation of effects into the implementation by using a suitable imperative language:
In a sense, I see us as in a worse position than before. Since the adoption of monadic <code>IO</code>, it’s been less immediately apparent that we’re still enslaved [...] Our current home is not painful enough to goad us onward, as were continuation-based I/O and stream-based I/O. (See [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.168.4008&rep=rep1&type=pdf A History of Haskell], section 7.1.) Nor does it fully liberate us.
 
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
<tt>[http://conal.net/blog/posts/can-functional-programming-be-liberated-from-the-von-neumann-paradigm Can functional programming be liberated from the von Neumann paradigm?], Conal Elliott.</tt><!-- 2010 -->
 
  +
Make no mistake, I don’t <i>want</i> to write systems software in a language like C++.
</div>
 
<br>
 
   
  +
<tt>[https://www.usenix.org/system/files/1311_05-08_mickens.pdf The Night Watch], James Mickens (page 3 of 4).</tt>
  +
</div>
  +
<sup> </sup>
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
My view is that the next logical step for programming is to split into two non-overlapping programming domains:
[...] Support for [external] state in Haskell exists in the form of the I/O monad[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.9725&rep=rep1&type=pdf <span></span>], but in our opinion the monadic idiom does not scale well to large, complexly stateful programs, and imposes constraints that are unnatural in the eyes of systems programmers.
 
   
  +
* runtime building for ...
<tt>[https://web.archive.org/web/20081212233905/http://www.bitc-lang.org/docs/bitc/bitc-origins.html The Origins of the BitC Programming Language], Jonathan Shapiro, Swaroop Sridhar and M. Scott Doerrie.</tt><!-- 2008 -->
 
  +
* ... mathematical programming languages
  +
  +
[...] Haskell is one example of a programming language where the code aspires to resemble pure mathematical expressions and definitions.
  +
  +
<tt>[https://www.haskellforall.com/2021/04/the-end-of-history-for-programming.html The end of history for programming], Gabriella Gonzalez.</tt>
 
</div>
 
</div>
  +
<br>
 
  +
So instead of having the denotative/imperative division within Haskell [https://dl.acm.org/doi/pdf/10.1145/319838.319848 by way of types], it would be at the language level in the forms of differing syntax and semantics, foreign calls, and so forth - an approach to be wary of in <i>any</i> major project, be it an implementation for some new programming language [[House|or an operating system]]:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
1. It demands far more implementation effort "beneath" the level of functional programming. It is the low level parts of operating systems whose semantics are most in doubt and where hidden bugs are most harmful: this is where functional programming is needed most!
[...] the next question that always comes up is how to do IO down in an function (in an expression) down a ways in the code. This often involves rewriting those "expressions" into "commands".
 
   
  +
2. It seems more liable to disaster from some hidden bug in the operating system. Merely discarding a pointer might discard the filing system, requiring recovery in some manner "outside" the operating system.
<tt>[http://blog.sigfpe.com/2007/11/io-monad-for-people-who-simply-dont.html#6353382341670425040 The IO Monad for People who Simply Don't Care], ''"jefu"''.</tt><!-- 2007 -->
 
  +
  +
<tt>[https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-56.pdf A New Scheme for Writing Functional Operating Systems], William Stoye (page 18 of 31).</tt>
 
</div>
 
</div>
  +
<br>
 
  +
This too could be alleviated by keeping the languages as similar as possible, but the logical conclusion of that endeavour is the two languages having only one point of difference - the imperative features - which would make having both languages effectively redundant:
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
3. It merely delays the issue of how one is to communicate with a persistent outside world. Sooner or later the question of interfacing to [networks, devices], remote filing systems and other computers must be faced.
<b>Booch</b>: What would be your advice to somebody that would want to take up the banner of functional programming? Where would you suggest they begin, and what hard problems would you like them to pursue?
 
  +
</div>
   
  +
== Open questions ==
<b>Backus</b>: Well, trying to functionalize all the input/output stuff.
 
   
  +
* Is there an alternate standalone model of I/O with less problems than each of the current models?
<b>Booch</b>: Helping it talk to the real world.
 
  +
* If not, can I/O be moved away from the language (as a model) and into the implementation (thus making the language denotative), while keeping the resulting language relatively practical to use?
   
  +
== Other questions ==
<b>Backus</b>: Yes.
 
  +
  +
* Is the C language "purely functional"?
  +
  +
::No:
  +
::* C isn't "pure" - it allows unrestricted access to observable effects, including those of I/O.
  +
::* C isn't "functional" - it was never intended to be [[Referential transparency|referentially transparent]], which severely restricts the ability to use [[Equational reasoning examples|equational reasoning]].
  +
  +
* Is the Haskell language "purely functional"?
  +
  +
::[https://chadaustin.me/2015/09/haskell-is-not-a-purely-functional-language Haskell is not a purely functional language], but is often described as being referentially transparent.
  +
  +
* Can functional programming be liberated from the von Neumann paradigm?
  +
  +
::Only if no-one proves it to be impossible (e.g. like trying to solve the halting problem).
  +
  +
* Why do our programs need to read input and write output?
  +
  +
::Because programs are usually written for practical purposes, such as implementing domain-specific [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.7.2089&rep=rep1&type=pdf little languages] like [https://dhall-lang.org Dhall].
  +
  +
== Other articles ==
  +
  +
* [https://core.ac.uk/download/pdf/82162724.pdf Functional Programming with Side Effects], Mark B. Josephs. <!-- 1986 -->
  +
  +
* [https://www.cs.unc.edu/techreports/88-022.pdf The Semantics of an FP Language with Infinite Objects], Teresa Thomas. <!-- 1988 -->
  +
  +
* [https://dl.acm.org/doi/pdf/10.1145/42192.42194 A Mathematical Approach to Nondeterminism in Data Types], Wim H. Hesselink. <!-- 1988 -->
  +
  +
* [https://www.cs.bham.ac.uk/~udr/papers/assign.pdf Assignments for Applicative Languages], Vipin Swarup, Uday S. Reddy and Evan Ireland. <!-- 1991 -->
  +
  +
* [https://www.cs.bham.ac.uk/~udr/papers/imperative-functional.pdf Imperative Functional Programming], Uday S. Reddy. <!-- 1996 -->
  +
  +
* [https://core.ac.uk/download/pdf/81924021.pdf A representable approach to finite nondeterminism], S. O. Anderson and A. J. Power. <!-- 1997 -->
  +
  +
* [https://repository.ubn.ru.nl/bitstream/handle/2066/17274/13362.pdf The impact of the lambda calculus in logic and computer science], Henk Barendregt. <!-- 1997 -->
  +
  +
* [https://core.ac.uk/download/pdf/82151892.pdf Interactive foundations of computing], Peter Wegner. <!-- 1998 -->
  +
  +
* [https://www.diva-portal.org/smash/get/diva2:1000395/FULLTEXT01.pdf Reactive Objects], Johan Nordlander, Mark P. Jones, Magnus Carlsson, Richard B. Kieburtz, and Andrew Black. <!-- 2002 -->
  +
  +
* [https://www.f.waseda.jp/terauchi/papers/toplas-witness.pdf Witnessing Side Effects], Tachio Terauchi and Alex Aiken. <!-- 2006 -->
  +
  +
* [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.7225&rep=rep1&type=pdf Programming Languages For Interactive Computing], Roly Perera. <!-- 2007 -->
  +
  +
* [https://staff.science.uva.nl/c.u.grelck/publications/HerhSchoGrelDAMP09.pdf Controlling Chaos: On Safe Side-Effects in Data-Parallel Operations], Stephan Herhut, Sven-Bodo Scholz and Clemens Grelck. <!-- 2009 -->
  +
  +
* [https://accu.org/index.php/journals/2199 On Zero-Side-Effect Interactive Programming, Actors, and FSMs], Sergey Ignatchenko. <!-- 2016 -->
  +
  +
* [https://plus.maths.org/content/category/tags/mathematical-mysteries Mathematical mysteries], <i>Plus</i> magazine.
  +
  +
=== More quotes ===
  +
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
[...] it is really quite annoying having to turn a nice elegant pure traversal of your AST into a monadic [I/O] beast [...]
   
  +
<tt>[https://discourse.haskell.org/t/solving-cyclic-boolean-implications-with-pure-code-and-laziness/4951 Solving cyclic boolean implications with pure code and laziness], Joachim Breitner.</tt><!-- 2022 -->
<tt>[https://archive.computerhistory.org/resources/text/Oral_History/Backus_John/Backus_John_1.oral_history.2006.102657970.pdf Oral History of John Backus], Grady Booch.</tt><!-- 2006 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
* Learn You A Haskell introduces I/O very late because it's a minor, ugly cousin feature of the language.
A recognised difficulty with using monads to enforce single-threaded access to the I/O world is that the programmer is forced to over-sequentialize their I/O code: I/O operations that are independent and which could be performed in any order still need to be given an explicit ordering in the program.
 
   
  +
<tt>[https://www.empirical.ee/learning-haskell Learning Haskell], Heath Raftery.</tt><!-- 2021 -->
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.4188&rep=rep1&type=pdf Modelling Deterministic Concurrent I/O], Malcolm Dowse and Andrew Butterfield.</tt><!-- 2006 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Haskell uses the seriously complex machinery of monads to do I/O, supposedly without side effects (I don't accept this). And you end up writing stuff [...] which to me looks like C. There must be a more functional approach.
The downside of I/O using monads is the need for a monad that can not be unwrapped. So, when using monadic I/O there is no way to get rid of the I/O monad. Furthermore, it is not as intuitive as one would like it to be. A prerequisite to good software design is a thorough understanding of the structures and glues of the implementation language. [...] Yet the understanding of monads is not trivial. The extensive amount of tutorials and questions on the Internet strengthen this thought.
 
   
<tt>[https://essay.utwente.nl/57287/1/scriptie_Rorije.pdf Input/Output in Functional Languages (Using Algebraic Union Types)], R.J. Rorije.</tt><!-- 2006 -->
+
<tt>[https://billwadge.wordpress.com/2021/05/22/monads-schmonads-functional-input-without-tears-pyfl Monads Schmonads: Functional Input without tears (PyFL)], Bill Wadge.</tt><!-- 2021 -->
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
In the pure functional[http://conal.net/blog/posts/the-c-language-is-purely-functional <span></span>] languages, Haskell and Clean, at present the most developed ones, the I/O problem is solved by respectively monads and uniqueness typing. But using these features, in both cases it is still possible to write incomprehensible code when dealing with I/O.
[...] doing IO in Haskell means using a polymorphic type as well as a mathematical theory that is rather obtuse. That's why IO is so far down in this tutorial.
 
   
  +
<tt>[https://lmcs.episciences.org/6755/pdf Gems of Corrado Böhm], Henk Barendregt (page 15 of 28, in footnote).</tt><!-- 2020 -->
<tt>[https://web.archive.org/web/20160408094723/http://www.kt.rim.or.jp/~kbk/haskell-intro/section3.html#part7 Haskell Tutorial for C Programmers], Eric Etheridge.</tt><!-- 2005 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Fundamentally, all functional languages are translated to an imperative language, and it leaks.
The common method to relieve the programming language designer from the inherent IO-problems is to shift responsibility to the programmer who has to sequentialize all IO-requests. This is also true for the monadic approach implemented in Haskell.
 
  +
  +
It leaks when you need to read and write files, when you need to respond to real-time user events, when you write to the screen or interact with the GPU, or when you communicate with an external process or API.
   
<tt>[https://core.ac.uk/download/pdf/14504553.pdf FUNDIO: A Lambda-Calculus With ''letrec'', ''case'', Constructors, and an IO-Interface:], Manfred Schmidt-Schauß.</tt><!-- 2003 -->
+
<tt>[https://myowenopinion.com/post/dev/functional-programming-is-a-leaky-abstraction Functional Programming Is a Leaky Abstraction], Owen Merkling.</tt><!-- 2020 -->
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
This is hard stuff. Two years ago I spent several hours to write 3 lines invoking IO computations.
[...] the monadic parts have a very imperative feel. I would be delighted to find a way to make it [...] more declarative.
 
   
  +
<tt>[https://discourse.haskell.org/t/trying-to-understand-the-io/1172/8 Trying to understand the <code>IO ()</code>], ''"belka"''.</tt><!-- 2020 -->
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.13.9123&rep=rep1&type=pdf Tackling the Awkward Squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell], Simon Peyton Jones.</tt><!-- 2001 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Shallow embeddings rely on an analogy between mathematical functions and procedures in a pure functional programming language. Effects, however, like state, I/O, and exceptions, can stretch this analogy too far.
The notation for interactive programs written in the monadic style is irritatingly close to the notation used in imperative languages.<br>
 
[...]<br>
 
Uniqueness typing addresses the more general problem of statically controlled use of resources in functional programs and, even if combined with passing unique representations of environment objects as arguments to these programs, it does not suffice to solve the input/output-problem. [...] The reason is that the environment is not updated in one conceptual step after the evaluation of a program [...] but rather in small steps whenever the environment representation is modified during program evaluation. The primitive interactions are thus implemented as side-effecting operations, the use of which is rendered safe in the uniqueness-typed environment passing framework.
 
<br>
 
[...]<br>
 
Similarly, monads are used to address the more general problem of computations (involving state, input/output, backtracking, ...) returning values: they do not solve any input/output-problems directly but rather provide an elegant and flexible abstraction of many solutions to related problems. [...] For instance, no less than three different input/output-schemes are used to solve these basic problems in [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.9725&rep=rep1&type=pdf Imperative functional programming], the paper which originally proposed `a new model, based on monads, for performing input/output in a non-strict, purely functional language'.<br>
 
[...]<br>
 
So, both input/output-schemes merely provide frameworks in which side-effecting operations can safely be used with a guaranteed order of execution and without affecting the properties of the purely functional parts of the language.
 
   
  +
<tt>[https://cakeml.org/ijcar18.pdf Proof-Producing Synthesis of CakeML with I/O and Local State from Monadic HOL Functions], Son Ho, Oskar Abrahamsson, Ramana Kumar, Magnus O. Myreen, Yong Kiam Tan, and Michael Norrish (page 2 of 16).</tt><!-- 2018 -->
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.9846&rep=rep1&type=pdf Functions, Frames and Interactions], Claus Reinke.</tt><!-- 1998 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Essentially, the Haskell type <code>IO t</code> combines both the features of [Idealised Algol's] <code>comm</code> and <code>exp</code>. This makes the [Haskell] framework slightly simpler, but it can be cumbersome if imperative computations are performed extensively.
How can we integrate interaction into a purely declarative language?<br>
 
[...]<br>
 
For Turing's machine, a calculation begins with a problem on its tape, and ends with an answer there. For Church's calculus, reduction begins with a lambda term, and ends with its normal form. For Floyd's flowcharts and Hoare's triples, a program begins in a state satisfying a precondition, and ends in a state satisfying a postcondition. How the initial tape or term or state is input, and how the final one is output, are questions neither asked or answered.
 
   
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.3579&rep=rep1&type=pdf How to Declare an Imperative], Philip Wadler.</tt><!-- 1997 -->
+
<tt>[https://www.cs.bham.ac.uk/~udr/popl/09-17-Algol-like.pdf Handout 9: Imperative programs and the Lambda Calculus], Uday Reddy (first page).</tt><!-- 2018 -->
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
I like the concise way of coding pure functions in Haskell using mathematical ideas like recursion and list comprehensions. However, user interactions are quite painful to implement using the I/O monad.
While it is fine that monadic I/O has good theoretical under-pinnings, did anyone stop to think if it helped in user interface programming? If all that it is is a means <i>somehow</i> to construct interactive programs, then it succeeds, but that is not enough. A programmer chooses a language based not on only on ability, but also usability.
 
   
<tt>[https://core.ac.uk/download/pdf/293056217.pdf Interacting with Functional Languages], Duncan Sinclair.</tt><!-- 1997 -->
+
<tt>[https://www.linkedin.com/pulse/definition-functional-programming-rainer-grimm The Definition of Functional Programming], Dirk Verlinden.</tt><!-- 2017 -->
 
</div>
 
</div>
 
<br>
 
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
If you find doing this separation [of code making I/O calls] annoying, you really wouldn’t like the machinations you have to do to mix pure and impure code in some functional languages (like Haskell).
   
  +
<tt>[https://refactoringjs.com/files/refactoring-javascript.pdf Refactoring JavaScript], Evan Burchard (page 437 of 499).</tt><!-- 2017 -->
  +
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
<code>IO</code> is indeed a monad instance, but not a very nice one - the compiler treats it specially, and it is not very nice to reason about [...]
Although the advantages of functional programming are fairly well known, a few areas have proved troublesome, I/O being one of these. [...]
 
   
  +
<tt>[https://nickhu.co.uk/Monads.pdf Understanding Monads], Nick Hu (first page).</tt><!-- 2016 -->
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.38.2254&rep=rep1&type=pdf Functional Languages and Graphical User Interfaces - a review and a case study], Rob Noble and Colin Runciman.</tt><!-- 1994 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Haskell compromises brilliantly, by fencing off pure and impure functions from one another [...] The illusion is so good that programmers are fooled into thinking I/O is pure in Haskell. And now that we can write mostly pure code with occasional impure wrappers, researchers have mostly stopped seeking superior alternatives.
Although we all love the beautiful aspects of functional languages we must admit that it is difficult to deal with a beast called Input-Output (I/O).
 
   
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.43.6060&rep=rep1&type=pdf The Beauty and the Beast], Peter Achten and Rinus Plasmeijer.</tt><!-- 1992 -->
+
<tt>[https://crypto.stanford.edu/~blynn/haskell/io.html A Problem With I/O], Ben Lynn.</tt><!-- 2016 -->
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
[...] you shouldn't spend much time writing <code>IO</code> stuff, because it's a bad language embedded in a good one.
One consequence of referential transparency is that it is difficult to incorporate I/O into a pure functional language. At least, the mechanism familiar to imperative programmers, say, a function of no arguments [...] which returns the next data item of a stream, would be impossible, since successive calls [...] ought to return different values. Alternative models have been proposed which do not suffer from this difficulty [...] Nonetheless, these other models are notationally complex, and I/O [modelling] remains a problem.
 
   
  +
<tt>[https://web.archive.org/web/20220309052143/http://comonad.com/reader/2015/on-the-unsafety-of-interleaved-io On the unsafety of interleaved I/O], Dan Doel.</tt><!-- 2015 -->
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.54.8751&rep=rep1&type=pdf Using a Lazy Functional Language for Textual Information Retrieval], Donald Ziff, Keith Waclena, and Stephen Spackman.</tt><!-- 1992 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Understanding I/O in Haskell, which implies understanding Monads (at least, the <code>IO</code> Monad) is actually one of the major difficulties I’ve came across while learning Haskell [...]
[...] A straightforward example of such a problematical application is that of a function which could allow us to interactively query and modify a database; this is clearly an interactive problem, since we may only be able to formulate queries once we have seen the responses to earlier ones.
 
   
  +
<tt>[https://discuss.codechef.com/t/is-it-possible-to-solve-tsort-with-haskell/4450 Is it possible to solve TSORT with Haskell?], Bruno Oliveira.</tt><!--2014 -->
<tt>[https://academic.oup.com/comjnl/article-pdf/32/2/162/1445725/320162.pdf Functional Programming and Operating Systems], Simon B. Jones and A. F. Sinclair.</tt><!-- 1989 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Here you’re equating functional languages with the inability to make use of benign effects, such as instrumentation of code for profiling purposes, which is indeed very clumsy in Haskell (you either have to rewrite your code to be imperative so that it conforms to the <code>IO</code> Monad, or else you have to admit that you really want ML [or perhaps HasFuse[https://www2.ki.informatik.uni-frankfurt.de/research/diamond/hasfuse/index.html <span></span>]] by using <code>unsafePerformIO</code>).
[...] Is there any hope of achieving <i>purely functional</i>, yet <i>universal</i>, and of course <i>efficient</i> I/O?
 
   
  +
<tt>[https://www.pl-enthusiast.net/2014/09/02/who-teaches-functional-programming/#comment-564 Who teaches functional programming?], Robert Harper.</tt><!-- 2014 -->
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.49.695&rep=rep1&type=pdf On the Expressiveness of Purely Functional I/O Systems], Paul Hudak and Raman S. Sundaresh.</tt><!-- 1989 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Although the functional programming community has solved many of the difficulties in implementation and use of functional languages, more research is needed [...] on facilities for input/output [...]
[...] many I/O schemes have been proposed for purely functional languages, but they tend to be <i>ad hoc</i> in the sense of being designed to express particular kinds of I/O, without aiming for universal power. [...]
 
   
<tt>[https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-160.pdf PFL+: a kernel scheme for functional I/O], Andrew Gordon.</tt><!-- 1989 -->
+
<tt>[https://john.cs.olemiss.edu/~hcc/csci555/notes/haskell_notes.pdf Notes on Functional Programming with Haskell], H. Conrad Cunningham (page 21 of 192).</tt> <!-- 2014 -->
 
</div>
 
</div>
 
<br>
 
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
IO in Haskell [is] for me a source of great displeasure and it just defeated every try I have given to learn the language.
Functional languages are extremely powerful and succinct tools for expressing algorithms[https://www.cambridge.org/9780521245036 <span></span>], but the way in which the results of such calculations should be communicated to the outside world is not obvious. [...]
 
   
  +
<tt>[https://www.haskellforall.com/2013/01/introduction-to-haskell-io.html?showComment=1361296801442#c794624017122358881 Introduction to Haskell <code>IO</code>], Ludovic Kuty.</tt><!-- 2013 -->
<tt>[https://core.ac.uk/download/pdf/82449736.pdf Message-based functional operating systems], Willian Stoye.</tt><!-- 1986 -->
 
 
</div>
 
</div>
 
<br>
 
<br>
 
__TOC__
 
 
== The I/O problem is mathematical in origin ==
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Stream transformers are fragile to use, continuations are powerful but somewhat clutter the syntax of functions. Monads and uniqueness types both present a trade-off, do we accept the over-sequentialisation imposed by monads, or the visual disorder of explicit environment passing? We believe that a compromise is still to be found [...]
Functional languages are entirely mathematical, so the places where they don't work show where computing is not mathematics and help to illuminate both fields.
 
   
<tt>[http://www.bitsavers.org/pdf/xerox/parc/techReports/CSL-81-11_Real_Programming_in_Functional_Languages.pdf Real Programming in Functional Languages], James H. Morris.</tt>
+
<tt>[https://www.owenstephens.co.uk/assets/static/research/masters_report.pdf Approaches to Functional I/O], Owen Stephens (final page).</tt><!-- 2011 -->
 
</div>
 
</div>
  +
<br>
 
One of those places is I/O and its observable effects:
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Once you’re in the IO monad, you’re stuck there forever, and are reduced to Algol-style imperative programming. You cannot easily convert between functional and monadic style without a radical restructuring of code.
The primary limitation of FP systems is that they are not history sensitive. Therefore they must be extended somehow before they can become practically useful.
 
   
  +
<tt>[https://existentialtype.wordpress.com/2011/05/01/of-course-ml-has-monads Of Course ML Has Monads!], Robert Harper.</tt><!-- 2011 -->
<tt>[https://www.cs.cmu.edu/~crary/819-f09/Backus78.pdf Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs], John Backus (page 11 of 29).</tt>
 
 
</div>
 
</div>
  +
<br>
<sup> </sup>
 
  +
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Input/output is awkward in declarative languages. Some functional languages like LISP have procedural read and write operations. Prolog has ugly read and write "predicates" that execute in sequence. Haskell monads provide pure functional I/O but still involve a sequence of actions.
To maintain correct I/O behaviour the relative temporal ordering of individual I/O operations must be controlled. [...] However, in pure functional languages [...] maintaining correct I/O behaviour is non-trivial [...] as a programmer needs always to be considering <i>how</i> something will be executed [...] a task from which functional programming is usually claimed to relieve the programmer.
 
   
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.628.7053&rep=rep1&type=pdf The implementation of practical functional programming languages], Nigel Perry.</tt>
+
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.227.6709&rep=rep1&type=pdf Specifying Input/Output by Enumeration], Walter W. Wilson and Yu Lei (first page).</tt><!-- 2010 -->
 
</div>
 
</div>
  +
<br>
<sup> </sup>
 
  +
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Support for [external] state in Haskell exists in the form of the I/O monad[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.9725&rep=rep1&type=pdf <span></span>], but in our opinion the monadic idiom does not scale well to large, complexly stateful programs, and imposes constraints that are unnatural in the eyes of systems programmers.
The programming style in a lazy functional language is heavily influenced by the supported I/O-mechanism. Modifying the I/O-behaviour or debugging some lazy functional program that uses I/O is a black art. It is interesting that novices in lazy functional programming in general expect that there is some direct (side-effecting) I/O using a function call.
 
   
  +
<tt>[https://web.archive.org/web/20081212233905/http://www.bitc-lang.org/docs/bitc/bitc-origins.html The Origins of the BitC Programming Language], Jonathan Shapiro, Swaroop Sridhar and M. Scott Doerrie.</tt><!-- 2008 -->
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.55.1076&rep=rep1&type=pdf A Partial Rehabilitation of Side-Effecting I/O:], Manfred Schmidt-Schauß.</tt>
 
 
</div>
 
</div>
  +
<br>
<sup> </sup>
 
  +
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Supporting IO would require us [...] to include relevant aspects of the outside system, plus some kind of nondeterminism for IO actions to take into account that we can never model the world in its entirety.
How must interactions between a program and an external environment (consisting of, e.g., input/output-devices, file systems, ...) be described in a programming language that abstracts from the existence of an outside world?
 
   
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.9846&rep=rep1&type=pdf Functions, Frames and Interactions], Claus Reinke (page 10 of 210).</tt>
+
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.176.4954&rep=rep1&type=pdf Imperative Functional Programming with Isabelle/HOL], Lukas Bulwahn, Alexander Krauss, Florian Haftmann, Levent Erkök and John Matthews (page 15 of 16).</tt><!-- 2008 -->
 
</div>
 
</div>
  +
<br>
<sup> </sup>
 
  +
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Unfortunately, a monadic programming style typically differs fundamentally from an ordinary functional style. While this is not as much of a problem if the programming task at hand is side-effecting by nature, it becomes an issue when side effects are only involved peripherally: then, a programmer will be keen to maintain a functional look and feel to the program and not have encapsulation of side effects dominate the overall style of the program.
Input/output is awkward in declarative languages. Some functional languages like LISP have procedural read and write operations. Prolog has ugly read and write "predicates" that execute in sequence. Haskell monads provide pure functional I/O but still involve a sequence of actions.
 
   
  +
<tt>[https://web.archive.org/web/20200930035115/https://www.holdermans.nl/pubs/assets/hage08heap.pdf Heap Recycling for Lazy Languages], Jurriaan Hage and Stefan Holdermans (first page).</tt><!-- 2008 -->
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.227.6709&rep=rep1&type=pdf Specifying Input/Output by Enumeration], Walter W. Wilson and Yu Lei.</tt>
 
 
</div>
 
</div>
  +
<br>
 
because the various fields of study collectively referred to as <i>mathematics</i> are abstract in one or more ways:
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
The common practice of mixing IO with functionality inhibits composability whether in C or in Haskell.
In a preliminary sense, mathematics is abstract because it is studied using highly general and formal resources.
 
   
  +
<tt>[http://conal.net/blog/posts/tangible-functional-programming-a-modern-marriage-of-usability-and-composability Tangible Functional Programming: a modern marriage of usability and composability], Conal Elliott.</tt><!-- 2007 -->
<tt>[https://iep.utm.edu/math-app The Applicability of Mathematics], from the [https://iep.utm.edu/ Internet Encyclopedia of Philosophy].</tt>
 
 
</div>
 
</div>
  +
<br>
 
In particular, they abstract away from the presence of an outside environment. For a declarative programming language like Haskell, which is based on one of these individual fields of study - higher-order functions - it should then be of little surprise that attempts to find a <i>"mathematical solution"</i> for I/O have been less than successful:
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
[...] the next question that always comes up is how to do IO down in an function (in an expression) down a ways in the code. This often involves rewriting those "expressions" into "commands".
Researchers began to analyze why it is often harder to prove things about programs written in traditional languages than it is to prove theorems about mathematics. Two aspects of traditional languages emerged as sources of trouble because they are <b>very difficult to model in a mathematical system</b>: mutability and sequencing.
 
   
  +
<tt>[http://blog.sigfpe.com/2007/11/io-monad-for-people-who-simply-dont.html#6353382341670425040 The IO Monad for People who Simply Don't Care], ''"jefu"''.</tt><!-- 2007 -->
<tt> [https://core.ac.uk/download/pdf/214330064.pdf The Anatomy of Programming Languages], Alice E. Fischer and Frances S. Grodzinsky (emphasis added).</tt>
 
 
</div>
 
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
* What would be ideal is an extension of one or more fields of mathematics which can [https://www.cs.kent.ac.uk/people/staff/dat/krc/paraffins-turner.pdf elegantly] describe interactions with external environments - the appropriate denotational semantics can then be used to map it into languages like Haskell.
 
  +
<b>Booch</b>: What would be your advice to somebody that would want to take up the banner of functional programming? Where would you suggest they begin, and what hard problems would you like them to pursue?
   
  +
<b>Backus</b>: Well, trying to functionalize all the input/output stuff.
* Alternately (and less ideally), if it can be proven that one cannot exist (like the solution to the halting problem) then implementors everywhere can just select the most-suitable model of I/O, as they see fit.
 
   
  +
<b>Booch</b>: Helping it talk to the real world.
== An axiomatic approach ==
 
   
  +
<b>Backus</b>: Yes.
The dependently-typed language Agda relies on Haskell for its outside interactions:
 
  +
  +
<tt>[https://archive.computerhistory.org/resources/text/Oral_History/Backus_John/Backus_John_1.oral_history.2006.102657970.pdf Oral History of John Backus], Grady Booch (pages 36-37 of 42).</tt><!-- 2006 -->
  +
</div>
  +
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
A recognised difficulty with using monads to enforce single-threaded access to the I/O world is that the programmer is forced to over-sequentialize their I/O code: I/O operations that are independent and which could be performed in any order still need to be given an explicit ordering in the program.
'''4 Compiling Agda programs'''
 
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.4188&rep=rep1&type=pdf Modelling Deterministic Concurrent I/O], Malcolm Dowse and Andrew Butterfield (page 2 of 12).</tt><!-- 2006 -->
This section deals with the topic of getting Agda programs to interact
 
with the real world. Type checking Agda programs requires evaluating
 
arbitrary terms, ans as long as all terms are pure and normalizing this is
 
not a problem, but what happens when we introduce side effects? Clearly,
 
we don't want side effects to happen at compile time. Another question is
 
what primitives the language should provide for constructing side effecing
 
programs. In Agda, these problems are solved by <i>allowing arbitrary
 
Haskell functions to be imported as axioms.</i> At compile time, these imported
 
functions have no reduction behaviour, <i>only at run time is the
 
Haskell function executed</i>.
 
 
<tt>[http://www.cse.chalmers.se/~ulfn/papers/afp08/tutorial.pdf Dependently Typed Programming in Agda], Ulf Norell and James Chapman (<i>emphasis added</i>).</tt>
 
 
</div>
 
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
Haskell's FFI also allows for arbitrary foreign code to be imported, to only be executed at run time:
 
  +
This [explicitly sequencing all I/O actions] is not abstract at all, and is hardly a better specification of I/O than any C or Pascal program.
   
  +
<tt>[https://www.scss.tcd.ie/publications/tech-reports/reports.06/TCD-CS-2006-19.pdf A Semantic Framework for Deterministic Functional Input/Output], Malcolm Dowse (page 17 of 224).</tt><!-- 2006 -->
<haskell>
 
  +
</div>
instance Monad IO where
 
  +
<br>
return = unitIO
 
(>>=) = bindIO
 
 
foreign import ccall "primUnitIO" unitIO :: a -> IO a
 
foreign import ccall "primBindIO" bindIO :: IO a -> (a -> IO b) -> IO b
 
 
</haskell>
 
 
However, Haskell 2010 doesn't allow higher-order FFI declarations, or their use of type variables. It is possible to devise simpler interfaces which can then be used to implement monadic I/O, but Haskell 2010 also imposes restrictions on its I/O type:
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
The downside of I/O using monads is the need for a monad that can not be unwrapped. So, when using monadic I/O there is no way to get rid of the I/O monad. Furthermore, it is not as intuitive as one would like it to be. A prerequisite to good software design is a thorough understanding of the structures and glues of the implementation language. [...] Yet the understanding of monads is not trivial. The extensive amount of tutorials and questions on the Internet strengthen this thought.
The <code>IO</code> type serves as a tag for operations (actions) that interact with the outside world. The <code>IO</code> type is abstract: no constructors are visible to the user.
 
   
<tt>[https://www.haskell.org/definition/haskell2010.pdf The Haskell 2010 Report] (page 95 of 329).</tt>
+
<tt>[https://essay.utwente.nl/57287/1/scriptie_Rorije.pdf Input/Output in Functional Languages (Using Algebraic Union Types)], R.J. Rorije (page 30 of 130).</tt><!-- 2006 -->
 
</div>
 
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
== On being denotative ==
 
  +
[...] doing IO in Haskell means using a polymorphic type as well as a mathematical theory that is rather obtuse. That's why IO is so far down in this tutorial.
   
  +
<tt>[https://web.archive.org/web/20160408094723/http://www.kt.rim.or.jp/~kbk/haskell-intro/section3.html#part7 Haskell Tutorial for C Programmers], Eric Etheridge.</tt><!-- 2005 -->
Instead of just being declarative, there have been calls for languages like Haskell to be [[Denotative|denotative]]:
 
  +
</div>
  +
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Haskell uses <i>monads</i> for destructive updates and I/O; they add a restricted form of stateful computation to a pure language, retaining referential transparency[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.3579&rep=rep1&type=pdf <span></span>]. The disadvantage is that programs become more complicated. Also, if imperative elements of a given application were not taken into account during its design but turn out to be necessary later on, often major parts have to be redesigned or (at least) reimplemented, especially because types change significantly. [...]
My vision of “solving the I/O problem” for functional programming is nothing like Haskell’s semantically imperative (non-)solution (called <code>IO</code> in Haskell), but rather to continue shifting semantically imperative mechanisms out of the programming model and into the implementation of (semantically simple) function application.
 
   
  +
The <tt>Truth</tt> team considers this point as one of the biggest drawbacks of the purely functional paradigm as followed by Haskell.
<tt>[http://conal.net/blog/posts/can-functional-programming-be-liberated-from-the-von-neumann-paradigm Conal Elliott.]</tt>
 
</div>
 
   
  +
<tt>[https://homepages.inf.ed.ac.uk/perdita/haskml.pdf Functional programming languages for verification tools: A comparison of Standard ML and Haskell], Martin Leucker, Thomas Noll, Perdita Stevens and Michael Weber (pages 12-13 of 22).</tt><!-- 2005 -->
because of how various other effects have already been moved out of languages and into their implementations:
 
  +
</div>
  +
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
It is possible that a declarative programming style for the IO part of a program can be integrated into Haskell.
[...] Underneath the implementation of our current functional abstractions (numbers, strings, trees, functions, etc), there are imperative mechanisms, such as memory allocation & deallocation, stack frame modification, and thunk overwriting (to implement laziness). [...]
 
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.69.4510&rep=rep1&type=pdf Realising nondeterministic I/O in the Glasgow Haskell Compiler], David Sabel (page 37 of 39).</tt><!-- 2003 -->
Stack and register munging and jump/<code>GOTO</code> are implementations of the semantically simpler notion of function application. (I mean “function” in the sense of math and of pure functional programming.) Moreover, stack & register munging is the input/output (IO) part of the implementation of function application. Information goes <b>out</b> of one context and <b>in</b>to another.
 
 
</div>
 
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
There is an assumption here:
 
  +
The common method to relieve the programming language designer from the inherent IO-problems is to shift responsibility to the programmer who has to sequentialize all IO-requests. This is also true for the monadic approach implemented in Haskell.
* I/O is just another <i>"imperative mechanism"</i>, no different from the rest, therefore it can be similarly sequestered (after all, they do ultimately rely on the same fetch and store operations provided by the solid-state Turing machine running the program).
 
   
  +
<tt>[https://core.ac.uk/download/pdf/14504553.pdf FUNDIO: A Lambda-Calculus With ''letrec'', ''case'', Constructors, and an IO-Interface:], Manfred Schmidt-Schauß (page 3 of 84).</tt><!-- 2003 -->
...which is false:
 
  +
</div>
* unlike those other memory-based mechanisms, the simplest of I/O is <b>device-based</b> and the exceedingly-vast majority of I/O devices do not behave like memory.
 
  +
<br>
 
But the historical precedent is compelling, and I/O may yet be confined to the implementation - it just requires a technique different to the ones used to relocate those other mechanisms:
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
In our approach, we would suggest to dismantle the <code>IO</code> monad into its constituting monads, and combine them [...] as needed. This has the advantage that the effects of most monads can be localised, so using e.g. state threads or exceptions in one part of the program will not make the type of every function using this part monadic, as is currently the case with the <code>IO</code> monad.
[...] we will someday really learn to look at [https://www.cs.columbia.edu/~hgs/internet/definition.html whole systems] in a consistently functional/denotational style (simple & precise semantics). [...]
 
  +
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.128.1864&rep=rep1&type=pdf Composing Monads Using Coproducts], Christoph Lüth and Neil Ghani (page 11 of 12).</tt><!-- 2002 -->
 
</div>
 
</div>
  +
<br>
 
[http://conal.net/blog/posts/can-functional-programming-be-liberated-from-the-von-neumann-paradigm#comment-598 As for the existence of] such a technique:
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
[...] the monadic parts have a very imperative feel. I would be delighted to find a way to make it [...] more declarative.
[...] I don’t care whether you’re playing “Yes, we can” or “No, we can’t”, so long as you’re rigorous. Rigorous proofs of possibility are usually (not always) constructive: demonstrate an example. That demonstration is what I’m working toward and inviting [[Denotative_programming_timeline|others]] along, as in this post and most of my other work.
 
  +
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.13.9123&rep=rep1&type=pdf Tackling the Awkward Squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell], Simon Peyton Jones (page 57 of 60).</tt><!-- 2001 -->
 
</div>
 
</div>
  +
<br>
 
Presumably the efforts to find that <i>"rigorous proof"</i> (for or against) are ongoing. Until then, the most prudent option is to use the model of I/O which is the least disruptive for languages like Haskell, and not just syntactically or semantically:
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Since I/O is by nature [reliant on] side effects, Haskell handles it differently. Monadic I/O is used to overcome this problem.
Unfortunately, a monadic programming style typically differs fundamentally from an ordinary functional style. While this is not as much of a problem if the programming task at hand is side-effecting by nature, it becomes an issue when side effects are only involved peripherally: then, a programmer will be keen to maintain a functional look and feel to the program and not have encapsulation of side effects dominate the overall style of the program.
 
   
  +
After overcoming [the problem of] Haskell's I/O, there were no more setbacks in writing the program.
<tt>[https://web.archive.org/web/20200930035115/https://www.holdermans.nl/pubs/assets/hage08heap.pdf Heap Recycling for Lazy Languages], Jurriaan Hage and Stefan Holdermans.</tt>
 
  +
  +
<tt>[https://www.mta.ca/~rrosebru/oldcourse/371199/haskell/paper.htm Functional Programming Using Haskell], Wade Estabrooks, Michael Goit and Mark Steeves.</tt><!-- 1999 -->
 
</div>
 
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
=== Using more than one language ===
 
  +
Ever since McCarthy[http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf <span></span>] referred to the input/output (I/O) operations <code>READ</code> and <code>PRINT</code> in LISP 1.5 as "pseudo-functions," I/O effects have been viewed with suspicion.
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.52.6409&rep=rep1&type=pdf Relating Operational and Denotational Semantics for Input/Output Effects], Roy L. Crole and Andrew D. Gordon (page 2 of 38).</tt><!-- 1999 -->
One suggestion is to ease the relocation of effects into the implementation by using a suitable imperative language:
 
  +
</div>
  +
<br>
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
Something fundamental and innocent looking as simple I/O has been a hard problem for functional languages.
My view is that the next logical step for programming is to split into two non-overlapping programming domains:
 
   
  +
<tt>[https://docs.andrewhenke.com/how-to-program/fps-sans-escher.pdf A Functional Pattern System for Object-Oriented Design], Thomas Kühne (page 40 of 346).</tt><!-- 1999 -->
* runtime building for ...
 
  +
</div>
* ... mathematical programming languages
 
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
[...] Haskell is one example of a programming language where the code aspires to resemble pure mathematical expressions and definitions.
 
  +
The notation for interactive programs written in the monadic style is irritatingly close to the notation used in imperative languages.<br>
  +
[...]<br>
  +
Uniqueness typing addresses the more general problem of statically controlled use of resources in functional programs and, even if combined with passing unique representations of environment objects as arguments to these programs, it does not suffice to solve the input/output-problem. [...] The reason is that the environment is not updated in one conceptual step after the evaluation of a program [...] but rather in small steps whenever the environment representation is modified during program evaluation. The primitive interactions are thus implemented as side-effecting operations, the use of which is rendered safe in the uniqueness-typed environment passing framework.
  +
<br>
  +
[...]<br>
  +
Similarly, monads are used to address the more general problem of computations (involving state, input/output, backtracking, ...) returning values: they do not solve any input/output-problems directly but rather provide an elegant and flexible abstraction of many solutions to related problems. [...] For instance, no less than three different input/output-schemes are used to solve these basic problems in [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.9725&rep=rep1&type=pdf Imperative functional programming], the paper which originally proposed ‘a new model, based on monads, for performing input/output in a non-strict, purely functional language’.<br>
  +
[...]<br>
  +
So, both input/output-schemes merely provide frameworks in which side-effecting operations can safely be used with a guaranteed order of execution and without affecting the properties of the purely functional parts of the language.
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.9846&rep=rep1&type=pdf Functions, Frames and Interactions], Claus Reinke (pages 96-97 of 210).</tt><!-- 1998 -->
<tt>[https://www.haskellforall.com/2021/04/the-end-of-history-for-programming.html Gabriella Gonzalez].</tt>
 
 
</div>
 
</div>
  +
<br>
 
So instead of having the denotative/imperative division within Haskell [https://dl.acm.org/doi/pdf/10.1145/319838.319848 by way of types], it would be at the language level in the forms of differing syntax and semantics, foreign calls, and so forth. This too could be alleviated by keeping both languages as similar as possible, but if this is taken to its logical conclusion then the only difference between the denotative and implementation languages would be just the imperative features, which would make having two such similar languages effectively redundant:
 
   
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
  +
While it is fine that monadic I/O has good theoretical under-pinnings, did anyone stop to think if it helped in user interface programming? If all that it is is a means <i>somehow</i> to construct interactive programs, then it succeeds, but that is not enough. A programmer chooses a language based not on only on ability, but also usability.
[...] It merely delays the issue of how one is to communicate with a persistent outside world. Sooner or later the question of interfacing to [networks], remote filing systems and other computers must be faced.
 
   
<tt>[https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-56.pdf A New Scheme for Writing Functional Operating Systems], William Stoye (page 18 of 31).</tt>
+
<tt>[https://core.ac.uk/download/pdf/293056217.pdf Interacting with Functional Languages], Duncan Sinclair (page 15 of 159).</tt><!-- 1997 -->
 
</div>
 
</div>
  +
<br>
<sup> </sup>
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
[...] Proving correctness is a formal activity. Therefore we must be able to lift an arbitrary implementation to the formal level. In order not to be forced to specify all details of an implementation, we have to admit nondeterminism on the formal level. It is especially useful in treating things like memory allocation, overflow conditions, and uninitialized fields of structured values [as well as [[Concurrency|concurrency]]].
 
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
The leading principle is to avoid premature or unnecessary design decisions. Therefore we have a preference for loose specifications, which admit a variety of nonisomorphic models. [...]
 
  +
The programming style in a lazy functional language is heavily influenced by the supported I/O-mechanism. Modifying the I/O-behaviour or debugging some lazy functional program that uses I/O is a black art. It is interesting that novices in lazy functional programming in general expect that there is some direct (side-effecting) I/O using a function call.
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.55.1076&rep=rep1&type=pdf A Partial Rehabilitation of Side-Effecting I/O:], Manfred Schmidt-Schauß (first page).</tt><!-- 1996 -->
<tt>[https://dl.acm.org/doi/pdf/10.1145/42192.42194 A Mathematical Approach to Nondeterminism in Data Types], Wim H. Hesselink.</tt>
 
 
</div>
 
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
== Open questions ==
 
  +
For other models of computation like functional or logic programming,
  +
the typical approach has been to add extra features implementing I/O. But
  +
these features do not fit in the nice and simple underlying model: in order
  +
to be able to understand or reason about programs involving I/O, the basic
  +
computational model has to be extended in non trivial ways, making it not so
  +
nice and simple anymore [...]
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.48.2591&rep=rep1&type=pdf Input/Output for ELAN], Patrick Viry (first page).</tt><!-- 1996 -->
* Is there an alternate standalone model of I/O with less problems than each of the current models?
 
  +
</div>
* If not, can I/O be moved away from the language (as a model) and into the implementation (thus making the language denotative), while keeping the resulting language relatively practical to use?
 
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
== Other questions ==
 
  +
Although the advantages of functional programming are fairly well known, a few areas have proved troublesome, I/O being one of these.
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.38.2254&rep=rep1&type=pdf Functional Languages and Graphical User Interfaces - a review and a case study], Rob Noble and Colin Runciman (page 6 of 51).</tt><!-- 1994 -->
* Is the C language "purely functional"?
 
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
::No:
 
  +
There are many attempts to integrate I/O into functional languages, such as linear types, and monads in Haskell, or uniqueness typing in Clean. These approaches have in common that the programmer explicitly has to create data dependencies among consecutive I/O operations which lead to very awkward notations.
::* C isn't "pure" - it allows unrestricted access to observable effects, including those of I/O.
 
::* C isn't "functional" - it was never intended to be [[Referential transparency|referentially transparent]], which severely restricts the ability to use [[Equational reasoning examples|equational reasoning]].
 
   
  +
<tt>[https://www.sac-home.org/_media/publications:pdf:sac-overview-norwich-94.pdf Single Assignment C - Functional Programming Using Imperative Style], Sven-Bodo Scholz (page 2 of 13).</tt><!-- 1994 -->
* Is the Haskell language "purely functional"?
 
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
::[https://chadaustin.me/2015/09/haskell-is-not-a-purely-functional-language Haskell is not a purely functional language], but is often described as being referentially transparent.
 
  +
Although we all love the beautiful aspects of functional languages we must admit that it is difficult to deal with a beast called Input-Output (I/O).
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.43.6060&rep=rep1&type=pdf The Beauty and the Beast], Peter Achten and Rinus Plasmeijer (first page).</tt><!-- 1992 -->
* Can functional programming be liberated from the von Neumann paradigm?
 
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
::Only if no-one proves it to be impossible (e.g. like trying to solve the halting problem).
 
  +
One consequence of referential transparency is that it is difficult to incorporate I/O into a pure functional language. At least, the mechanism familiar to imperative programmers, say, a function of no arguments [...] which returns the next data item of a stream, would be impossible, since successive calls [...] ought to return different values. Alternative models have been proposed which do not suffer from this difficulty [...] Nonetheless, these other models are notationally complex, and I/O [modelling] remains a problem.
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.54.8751&rep=rep1&type=pdf Using a Lazy Functional Language for Textual Information Retrieval], Donald Ziff, Keith Waclena, and Stephen Spackman (page 3 0f 13).</tt><!-- 1992 -->
* Why do our programs need to read input and write output?
 
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
::Because programs are usually written for practical purposes, such as implementing domain-specific [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.7.2089&rep=rep1&type=pdf little languages] like [https://dhall-lang.org Dhall].
 
  +
To maintain correct I/O behaviour the relative temporal ordering of individual I/O operations must be controlled. [...] However, in pure functional languages [...] maintaining correct I/O behaviour is non-trivial [...] as a programmer needs always to be considering <i>how</i> something will be executed [...] a task from which functional programming is usually claimed to relieve the programmer.
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.628.7053&rep=rep1&type=pdf The implementation of practical functional programming languages], Nigel Perry (page 18 0f 144, in footnote).</tt><!-- 1990 -->
== Other articles ==
 
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
* [https://core.ac.uk/download/pdf/82162724.pdf Functional Programming with Side Effects], Mark B. Josephs. <!-- 1986 -->
 
  +
A straightforward example of such a problematical application is that of a function which could allow us to interactively query and modify a database; this is clearly an interactive problem, since we may only be able to formulate queries once we have seen the responses to earlier ones.
   
  +
<tt>[https://academic.oup.com/comjnl/article-pdf/32/2/162/1445725/320162.pdf Functional Programming and Operating Systems], Simon B. Jones and A. F. Sinclair (first page).</tt><!-- 1989 -->
* [https://www.cs.unc.edu/techreports/88-022.pdf The Semantics of an FP Language with Infinite Objects], Teresa Thomas. <!-- 1988 -->
 
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
* [https://www.cs.ox.ac.uk/files/3404/PRG82.pdf A Functional Database], Phil Trinder. <!-- 1989 -->
 
  +
At present most declarative languages are guest languages on [...] procedural machines, and able to preserve their data in the file system provided by the host machine. However, the interface to the file system that is provided by the guest languages is primitive and often not referentially transparent.
   
* [https://www.cs.bham.ac.uk/~udr/papers/assign.pdf Assignments for Applicative Languages], Vipin Swarup, Uday S. Reddy and Evan Ireland. <!-- 1991 -->
+
<tt>[https://www.cs.ox.ac.uk/files/3404/PRG82.pdf A Functional Database], Phil Trinder (page 14 of 210).</tt><!-- 1989 -->
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
* [https://www.cs.bham.ac.uk/~udr/papers/imperative-functional.pdf Imperative Functional Programming], Uday S. Reddy. <!-- 1996 -->
 
  +
Is there any hope of achieving <i>purely functional</i>, yet <i>universal</i>, and of course <i>efficient</i> I/O?
   
  +
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.49.695&rep=rep1&type=pdf On the Expressiveness of Purely Functional I/O Systems], Paul Hudak and Raman S. Sundaresh (page 2 of 28).</tt><!-- 1989 -->
* [https://core.ac.uk/download/pdf/82151892.pdf Interactive foundations of computing], Peter Wegner. <!-- 1998 -->
 
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
* [https://maartenfokkinga.github.io/utwente/mmf2001c.pdf An alternative approach to I/O], Maarten Fokkinga and Jan Kuper. <!-- 2001 -->
 
  +
[...] many I/O schemes have been proposed for purely functional languages, but they tend to be <i>ad hoc</i> in the sense of being designed to express particular kinds of I/O, without aiming for universal power.
   
* [https://www.diva-portal.org/smash/get/diva2:1000395/FULLTEXT01.pdf Reactive Objects], Johan Nordlander, Mark P. Jones, Magnus Carlsson, Richard B. Kieburtz, and Andrew Black. <!-- 2002 -->
+
<tt>[https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-160.pdf PFL+: a kernel scheme for functional I/O], Andrew Gordon (page 4 of 28).</tt><!-- 1989 -->
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
* [https://www.f.waseda.jp/terauchi/papers/toplas-witness.pdf Witnessing Side Effects], Tachio Terauchi and Alex Aiken. <!-- 2006 -->
 
  +
Functional languages are extremely powerful and succinct tools for expressing algorithms[https://www.cambridge.org/9780521245036 <span></span>], but the way in which the results of such calculations should be communicated to the outside world is not obvious.
   
* [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.7225&rep=rep1&type=pdf Programming Languages For Interactive Computing], Roly Perera. <!-- 2007 -->
+
<tt>[https://core.ac.uk/download/pdf/82449736.pdf Message-based functional operating systems], Willian Stoye (first page).</tt><!-- 1986 -->
  +
</div>
  +
<br>
   
  +
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
* [https://www.researchgate.net/profile/Clemens-Grelck/publication/220997216_Controlling_chaos_on_safe_side-effects_in_data-parallel_operations/links/543bb4670cf2d6698be31618/Controlling-chaos-on-safe-side-effects-in-data-parallel-operations.pdf Controlling Chaos: On Safe Side-Effects in Data-Parallel Operations], Stephan Herhut, Sven-Bodo Scholz and Clemens Grelck. <!-- 2009 -->
 
  +
The primary limitation of FP systems is that they are not history sensitive. Therefore they must be extended somehow before they can become practically useful.
   
  +
<tt>[https://www.cs.cmu.edu/~crary/819-f09/Backus78.pdf Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs], John Backus (page 11 of 29).</tt><!-- 1978 -->
* [https://accu.org/index.php/journals/2199 On Zero-Side-Effect Interactive Programming, Actors, and FSMs], Sergey Ignatchenko. <!-- 2016 -->
 
  +
</div>
   
  +
[[Category:Mathematics]]
 
[[Category:Research]]
 
[[Category:Research]]

Revision as of 12:12, 5 December 2022

Functional languages are entirely mathematical, so the places where they don't work show where computing is not mathematics and help to illuminate both fields.

Real Programming in Functional Languages, James H. Morris (page 33 of 36).

One of those places is I/O:

How the initial [lambda term] is input, and how the final one is output, are questions neither asked or answered.

How to Declare an Imperative, Philip Wadler (page 2 of 33).

The problem is mathematical in origin

The various fields of study collectively referred to as mathematics are abstract in one or more ways:

In a preliminary sense, mathematics is abstract because it is studied using highly general and formal resources.

The Applicability of Mathematics, from the Internet Encyclopedia of Philosophy.

In particular, they abstract away from the presence of an outside environment. For a declarative programming language like Haskell, which is based on one of these individual fields of study - higher-order functions - this raises the question of I/O and its observable effects:

How must interactions between a program and an external environment (consisting of, e.g., input/output-devices, file systems, ...) be described in a programming language that abstracts from the existence of an outside world?

Functions, Frames and Interactions, Claus Reinke (page 10 of 210).

It should then be of little surprise that attempts to find a satisfactory mathematical solution for I/O have been less than successful:

During the 1960s, several researchers began work on proving things about programs. [...]

Several difficult problems emerged from this work. One was the problem of specification: before one can prove that a program is correct, one must specify the meaning of "correct", formally and unambiguously. Formal systems for specifying the meaning of a program were developed, and they looked suspiciously like programming languages.

Researchers began to analyze why it is often harder to prove things about programs written in traditional languages than it is to prove theorems about mathematics. Two aspects of traditional languages emerged as sources of trouble because they are very difficult to model in a mathematical system: mutability and sequencing.

The Anatomy of Programming Languages, Alice E. Fischer and Frances S. Grodzinsky (page 353 of 600).

  • mutability:

There is in principle nothing to stop functional programs from passing a single extra parameter into and out of every single function in the entire system. If this extra parameter were a collection (compound value) of some kind then it could be used to simulate an arbitrarily large set of mutable variables. In effect this approach recreates a single pool of global variables - hence, even though referential transparency is maintained, ease of reasoning is lost (we still know that each function is dependent only upon its arguments, but one of them has become so large and contains irrelevant values that the benefit of this knowledge as an aid to understanding is almost nothing).

Out of the Tar Pit, Ben Moseley and Peter Marks (page 17 of 66).

  • sequencing:

We have experimented for some time with a means for the programmer to specify a ‘syntactic’ partial order between subexpressions, with the intended effect that the ‘semantic’ order in which the input actions occur during the evaluation is not in conflict with the specified ‘syntactic’ partial order on the subexpressions (which carries over to the input actions evoked by those subexpressions). As a consequence, whenever the evaluator is about to execute an input action, it first has to decide whether there will occur in the future another input action that should be done first according to the specified ‘syntactic’ partial order. That problem, however, is undecidable.

An alternative approach to I/O, Maarten Fokkinga and Jan Kuper (page 6 of 12).

So where to from here?

  • What would be ideal is an extension of one or more fields of mathematics which can elegantly describe interactions with external environments - the appropriate denotational semantics can then be used to map it into languages like Haskell.
  • Alternately (and less ideally), if it can be proven that one cannot exist (like the solution to the halting problem) then implementors everywhere can just select the most-suitable model of I/O, as they see fit.

An axiomatic approach

The dependently-typed language Agda relies on Haskell for its outside interactions:

4 Compiling Agda programs

This section deals with the topic of getting Agda programs to interact with the real world. Type checking Agda programs requires evaluating arbitrary terms, ans as long as all terms are pure and normalizing this is not a problem, but what happens when we introduce side effects? Clearly, we don't want side effects to happen at compile time. Another question is what primitives the language should provide for constructing side effecing programs. In Agda, these problems are solved by allowing arbitrary Haskell functions to be imported as axioms. At compile time, these imported functions have no reduction behaviour, only at run time is the Haskell function executed.

Dependently Typed Programming in Agda, Ulf Norell and James Chapman (page 38 of 41).

Haskell's FFI also allows for arbitrary foreign code to be imported, to only be executed at run time:

instance Monad IO where
    return = unitIO
    (>>=)  = bindIO
    
foreign import ccall "primUnitIO" unitIO :: a -> IO a
foreign import ccall "primBindIO" bindIO :: IO a -> (a -> IO b) -> IO b
                

However, Haskell 2010 doesn't allow higher-order FFI declarations, or their use of type variables. Visible implementations of monadic I/O based on other interfaces are another option, but Haskell 2010 also imposes restrictions on its I/O type:

The IO type serves as a tag for operations (actions) that interact with the outside world. The IO type is abstract: no constructors are visible to the user.

The Haskell 2010 Report (page 95 of 329).

On being denotative

Instead of just being declarative, there have been calls for languages like Haskell to be denotative:

My vision of “solving the I/O problem” for functional programming is nothing like Haskell’s semantically imperative (non-)solution (called IO in Haskell), but rather to continue shifting semantically imperative mechanisms out of the programming model and into the implementation of (semantically simple) function application.

Can functional programming be liberated from the von Neumann paradigm?, Conal Elliott.

As a result of that semantic simplicity:

A functional program transforms data into other data according to a certain algorithm. Functional programs cannot deal with input/output, cannot switch on and off lamps depending on the value of a certain parameter; in general they cannot deal with process control.

These points are sometimes held as arguments against functional programming. However a reduction machine [specifically designed for the execution of functional languages] can produce code for process control, code that is executed by some interface. A von Neumann computer also needs interfaces for I/O and other controls. Therefore, a reduction machine with environment will consist of a pure reduction machine (dealing with algorithms that transform data) together with interfaces for process control (like I/O), see Fig. 1.

Functional Programming and Lambda Calculus, Henk Barendregt (pages 324-325).

...an environment?

The purely functional reduction machine is attached to a von Neumann host machine and an imperative environment deals with I/O and interactive programs.

Functional programming and the language TALE, Henk Barendregt and Marc van Leeuwen (page 126).

This vision of “solving the I/O problem” was a “standard” common solution in the past:

Research is [still] being done to find other solutions.

Using more than one language

One suggestion is to ease the relocation of effects into the implementation by using a suitable imperative language:

Make no mistake, I don’t want to write systems software in a language like C++.

The Night Watch, James Mickens (page 3 of 4).

My view is that the next logical step for programming is to split into two non-overlapping programming domains:

  • runtime building for ...
  • ... mathematical programming languages

[...] Haskell is one example of a programming language where the code aspires to resemble pure mathematical expressions and definitions.

The end of history for programming, Gabriella Gonzalez.

So instead of having the denotative/imperative division within Haskell by way of types, it would be at the language level in the forms of differing syntax and semantics, foreign calls, and so forth - an approach to be wary of in any major project, be it an implementation for some new programming language or an operating system:

1. It demands far more implementation effort "beneath" the level of functional programming. It is the low level parts of operating systems whose semantics are most in doubt and where hidden bugs are most harmful: this is where functional programming is needed most!

2. It seems more liable to disaster from some hidden bug in the operating system. Merely discarding a pointer might discard the filing system, requiring recovery in some manner "outside" the operating system.

A New Scheme for Writing Functional Operating Systems, William Stoye (page 18 of 31).

This too could be alleviated by keeping the languages as similar as possible, but the logical conclusion of that endeavour is the two languages having only one point of difference - the imperative features - which would make having both languages effectively redundant:

3. It merely delays the issue of how one is to communicate with a persistent outside world. Sooner or later the question of interfacing to [networks, devices], remote filing systems and other computers must be faced.

Open questions

  • Is there an alternate standalone model of I/O with less problems than each of the current models?
  • If not, can I/O be moved away from the language (as a model) and into the implementation (thus making the language denotative), while keeping the resulting language relatively practical to use?

Other questions

  • Is the C language "purely functional"?
No:
  • C isn't "pure" - it allows unrestricted access to observable effects, including those of I/O.
  • C isn't "functional" - it was never intended to be referentially transparent, which severely restricts the ability to use equational reasoning.
  • Is the Haskell language "purely functional"?
Haskell is not a purely functional language, but is often described as being referentially transparent.
  • Can functional programming be liberated from the von Neumann paradigm?
Only if no-one proves it to be impossible (e.g. like trying to solve the halting problem).
  • Why do our programs need to read input and write output?
Because programs are usually written for practical purposes, such as implementing domain-specific little languages like Dhall.

Other articles

  • Reactive Objects, Johan Nordlander, Mark P. Jones, Magnus Carlsson, Richard B. Kieburtz, and Andrew Black.

More quotes

[...] it is really quite annoying having to turn a nice elegant pure traversal of your AST into a monadic [I/O] beast [...]

Solving cyclic boolean implications with pure code and laziness, Joachim Breitner.


  • Learn You A Haskell introduces I/O very late because it's a minor, ugly cousin feature of the language.

Learning Haskell, Heath Raftery.


Haskell uses the seriously complex machinery of monads to do I/O, supposedly without side effects (I don't accept this). And you end up writing stuff [...] which to me looks like C. There must be a more functional approach.

Monads Schmonads: Functional Input without tears (PyFL), Bill Wadge.


In the pure functional languages, Haskell and Clean, at present the most developed ones, the I/O problem is solved by respectively monads and uniqueness typing. But using these features, in both cases it is still possible to write incomprehensible code when dealing with I/O.

Gems of Corrado Böhm, Henk Barendregt (page 15 of 28, in footnote).


Fundamentally, all functional languages are translated to an imperative language, and it leaks.

It leaks when you need to read and write files, when you need to respond to real-time user events, when you write to the screen or interact with the GPU, or when you communicate with an external process or API.

Functional Programming Is a Leaky Abstraction, Owen Merkling.


This is hard stuff. Two years ago I spent several hours to write 3 lines invoking IO computations.

Trying to understand the IO (), "belka".


Shallow embeddings rely on an analogy between mathematical functions and procedures in a pure functional programming language. Effects, however, like state, I/O, and exceptions, can stretch this analogy too far.

Proof-Producing Synthesis of CakeML with I/O and Local State from Monadic HOL Functions, Son Ho, Oskar Abrahamsson, Ramana Kumar, Magnus O. Myreen, Yong Kiam Tan, and Michael Norrish (page 2 of 16).


Essentially, the Haskell type IO t combines both the features of [Idealised Algol's] comm and exp. This makes the [Haskell] framework slightly simpler, but it can be cumbersome if imperative computations are performed extensively.

Handout 9: Imperative programs and the Lambda Calculus, Uday Reddy (first page).


I like the concise way of coding pure functions in Haskell using mathematical ideas like recursion and list comprehensions. However, user interactions are quite painful to implement using the I/O monad.

The Definition of Functional Programming, Dirk Verlinden.


If you find doing this separation [of code making I/O calls] annoying, you really wouldn’t like the machinations you have to do to mix pure and impure code in some functional languages (like Haskell).

Refactoring JavaScript, Evan Burchard (page 437 of 499).


IO is indeed a monad instance, but not a very nice one - the compiler treats it specially, and it is not very nice to reason about [...]

Understanding Monads, Nick Hu (first page).


Haskell compromises brilliantly, by fencing off pure and impure functions from one another [...] The illusion is so good that programmers are fooled into thinking I/O is pure in Haskell. And now that we can write mostly pure code with occasional impure wrappers, researchers have mostly stopped seeking superior alternatives.

A Problem With I/O, Ben Lynn.


[...] you shouldn't spend much time writing IO stuff, because it's a bad language embedded in a good one.

On the unsafety of interleaved I/O, Dan Doel.


Understanding I/O in Haskell, which implies understanding Monads (at least, the IO Monad) is actually one of the major difficulties I’ve came across while learning Haskell [...]

Is it possible to solve TSORT with Haskell?, Bruno Oliveira.


Here you’re equating functional languages with the inability to make use of benign effects, such as instrumentation of code for profiling purposes, which is indeed very clumsy in Haskell (you either have to rewrite your code to be imperative so that it conforms to the IO Monad, or else you have to admit that you really want ML [or perhaps HasFuse] by using unsafePerformIO).

Who teaches functional programming?, Robert Harper.


Although the functional programming community has solved many of the difficulties in implementation and use of functional languages, more research is needed [...] on facilities for input/output [...]

Notes on Functional Programming with Haskell, H. Conrad Cunningham (page 21 of 192).


IO in Haskell [is] for me a source of great displeasure and it just defeated every try I have given to learn the language.

Introduction to Haskell IO, Ludovic Kuty.


Stream transformers are fragile to use, continuations are powerful but somewhat clutter the syntax of functions. Monads and uniqueness types both present a trade-off, do we accept the over-sequentialisation imposed by monads, or the visual disorder of explicit environment passing? We believe that a compromise is still to be found [...]

Approaches to Functional I/O, Owen Stephens (final page).


Once you’re in the IO monad, you’re stuck there forever, and are reduced to Algol-style imperative programming. You cannot easily convert between functional and monadic style without a radical restructuring of code.

Of Course ML Has Monads!, Robert Harper.


Input/output is awkward in declarative languages. Some functional languages like LISP have procedural read and write operations. Prolog has ugly read and write "predicates" that execute in sequence. Haskell monads provide pure functional I/O but still involve a sequence of actions.

Specifying Input/Output by Enumeration, Walter W. Wilson and Yu Lei (first page).


Support for [external] state in Haskell exists in the form of the I/O monad, but in our opinion the monadic idiom does not scale well to large, complexly stateful programs, and imposes constraints that are unnatural in the eyes of systems programmers.

The Origins of the BitC Programming Language, Jonathan Shapiro, Swaroop Sridhar and M. Scott Doerrie.


Supporting IO would require us [...] to include relevant aspects of the outside system, plus some kind of nondeterminism for IO actions to take into account that we can never model the world in its entirety.

Imperative Functional Programming with Isabelle/HOL, Lukas Bulwahn, Alexander Krauss, Florian Haftmann, Levent Erkök and John Matthews (page 15 of 16).


Unfortunately, a monadic programming style typically differs fundamentally from an ordinary functional style. While this is not as much of a problem if the programming task at hand is side-effecting by nature, it becomes an issue when side effects are only involved peripherally: then, a programmer will be keen to maintain a functional look and feel to the program and not have encapsulation of side effects dominate the overall style of the program.

Heap Recycling for Lazy Languages, Jurriaan Hage and Stefan Holdermans (first page).


The common practice of mixing IO with functionality inhibits composability whether in C or in Haskell.

Tangible Functional Programming: a modern marriage of usability and composability, Conal Elliott.


[...] the next question that always comes up is how to do IO down in an function (in an expression) down a ways in the code. This often involves rewriting those "expressions" into "commands".

The IO Monad for People who Simply Don't Care, "jefu".


Booch: What would be your advice to somebody that would want to take up the banner of functional programming? Where would you suggest they begin, and what hard problems would you like them to pursue?

Backus: Well, trying to functionalize all the input/output stuff.

Booch: Helping it talk to the real world.

Backus: Yes.

Oral History of John Backus, Grady Booch (pages 36-37 of 42).


A recognised difficulty with using monads to enforce single-threaded access to the I/O world is that the programmer is forced to over-sequentialize their I/O code: I/O operations that are independent and which could be performed in any order still need to be given an explicit ordering in the program.

Modelling Deterministic Concurrent I/O, Malcolm Dowse and Andrew Butterfield (page 2 of 12).


This [explicitly sequencing all I/O actions] is not abstract at all, and is hardly a better specification of I/O than any C or Pascal program.

A Semantic Framework for Deterministic Functional Input/Output, Malcolm Dowse (page 17 of 224).


The downside of I/O using monads is the need for a monad that can not be unwrapped. So, when using monadic I/O there is no way to get rid of the I/O monad. Furthermore, it is not as intuitive as one would like it to be. A prerequisite to good software design is a thorough understanding of the structures and glues of the implementation language. [...] Yet the understanding of monads is not trivial. The extensive amount of tutorials and questions on the Internet strengthen this thought.

Input/Output in Functional Languages (Using Algebraic Union Types), R.J. Rorije (page 30 of 130).


[...] doing IO in Haskell means using a polymorphic type as well as a mathematical theory that is rather obtuse. That's why IO is so far down in this tutorial.

Haskell Tutorial for C Programmers, Eric Etheridge.


Haskell uses monads for destructive updates and I/O; they add a restricted form of stateful computation to a pure language, retaining referential transparency. The disadvantage is that programs become more complicated. Also, if imperative elements of a given application were not taken into account during its design but turn out to be necessary later on, often major parts have to be redesigned or (at least) reimplemented, especially because types change significantly. [...]

The Truth team considers this point as one of the biggest drawbacks of the purely functional paradigm as followed by Haskell.

Functional programming languages for verification tools: A comparison of Standard ML and Haskell, Martin Leucker, Thomas Noll, Perdita Stevens and Michael Weber (pages 12-13 of 22).


It is possible that a declarative programming style for the IO part of a program can be integrated into Haskell.

Realising nondeterministic I/O in the Glasgow Haskell Compiler, David Sabel (page 37 of 39).


The common method to relieve the programming language designer from the inherent IO-problems is to shift responsibility to the programmer who has to sequentialize all IO-requests. This is also true for the monadic approach implemented in Haskell.

FUNDIO: A Lambda-Calculus With letrec, case, Constructors, and an IO-Interface:, Manfred Schmidt-Schauß (page 3 of 84).


In our approach, we would suggest to dismantle the IO monad into its constituting monads, and combine them [...] as needed. This has the advantage that the effects of most monads can be localised, so using e.g. state threads or exceptions in one part of the program will not make the type of every function using this part monadic, as is currently the case with the IO monad.

Composing Monads Using Coproducts, Christoph Lüth and Neil Ghani (page 11 of 12).


[...] the monadic parts have a very imperative feel. I would be delighted to find a way to make it [...] more declarative.

Tackling the Awkward Squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell, Simon Peyton Jones (page 57 of 60).


Since I/O is by nature [reliant on] side effects, Haskell handles it differently. Monadic I/O is used to overcome this problem.

After overcoming [the problem of] Haskell's I/O, there were no more setbacks in writing the program.

Functional Programming Using Haskell, Wade Estabrooks, Michael Goit and Mark Steeves.


Ever since McCarthy referred to the input/output (I/O) operations READ and PRINT in LISP 1.5 as "pseudo-functions," I/O effects have been viewed with suspicion.

Relating Operational and Denotational Semantics for Input/Output Effects, Roy L. Crole and Andrew D. Gordon (page 2 of 38).


Something fundamental and innocent looking as simple I/O has been a hard problem for functional languages.

A Functional Pattern System for Object-Oriented Design, Thomas Kühne (page 40 of 346).


The notation for interactive programs written in the monadic style is irritatingly close to the notation used in imperative languages.
[...]
Uniqueness typing addresses the more general problem of statically controlled use of resources in functional programs and, even if combined with passing unique representations of environment objects as arguments to these programs, it does not suffice to solve the input/output-problem. [...] The reason is that the environment is not updated in one conceptual step after the evaluation of a program [...] but rather in small steps whenever the environment representation is modified during program evaluation. The primitive interactions are thus implemented as side-effecting operations, the use of which is rendered safe in the uniqueness-typed environment passing framework.
[...]
Similarly, monads are used to address the more general problem of computations (involving state, input/output, backtracking, ...) returning values: they do not solve any input/output-problems directly but rather provide an elegant and flexible abstraction of many solutions to related problems. [...] For instance, no less than three different input/output-schemes are used to solve these basic problems in Imperative functional programming, the paper which originally proposed ‘a new model, based on monads, for performing input/output in a non-strict, purely functional language’.
[...]
So, both input/output-schemes merely provide frameworks in which side-effecting operations can safely be used with a guaranteed order of execution and without affecting the properties of the purely functional parts of the language.

Functions, Frames and Interactions, Claus Reinke (pages 96-97 of 210).


While it is fine that monadic I/O has good theoretical under-pinnings, did anyone stop to think if it helped in user interface programming? If all that it is is a means somehow to construct interactive programs, then it succeeds, but that is not enough. A programmer chooses a language based not on only on ability, but also usability.

Interacting with Functional Languages, Duncan Sinclair (page 15 of 159).


The programming style in a lazy functional language is heavily influenced by the supported I/O-mechanism. Modifying the I/O-behaviour or debugging some lazy functional program that uses I/O is a black art. It is interesting that novices in lazy functional programming in general expect that there is some direct (side-effecting) I/O using a function call.

A Partial Rehabilitation of Side-Effecting I/O:, Manfred Schmidt-Schauß (first page).


For other models of computation like functional or logic programming, the typical approach has been to add extra features implementing I/O. But these features do not fit in the nice and simple underlying model: in order to be able to understand or reason about programs involving I/O, the basic computational model has to be extended in non trivial ways, making it not so nice and simple anymore [...]

Input/Output for ELAN, Patrick Viry (first page).


Although the advantages of functional programming are fairly well known, a few areas have proved troublesome, I/O being one of these.

Functional Languages and Graphical User Interfaces - a review and a case study, Rob Noble and Colin Runciman (page 6 of 51).


There are many attempts to integrate I/O into functional languages, such as linear types, and monads in Haskell, or uniqueness typing in Clean. These approaches have in common that the programmer explicitly has to create data dependencies among consecutive I/O operations which lead to very awkward notations.

Single Assignment C - Functional Programming Using Imperative Style, Sven-Bodo Scholz (page 2 of 13).


Although we all love the beautiful aspects of functional languages we must admit that it is difficult to deal with a beast called Input-Output (I/O).

The Beauty and the Beast, Peter Achten and Rinus Plasmeijer (first page).


One consequence of referential transparency is that it is difficult to incorporate I/O into a pure functional language. At least, the mechanism familiar to imperative programmers, say, a function of no arguments [...] which returns the next data item of a stream, would be impossible, since successive calls [...] ought to return different values. Alternative models have been proposed which do not suffer from this difficulty [...] Nonetheless, these other models are notationally complex, and I/O [modelling] remains a problem.

Using a Lazy Functional Language for Textual Information Retrieval, Donald Ziff, Keith Waclena, and Stephen Spackman (page 3 0f 13).


To maintain correct I/O behaviour the relative temporal ordering of individual I/O operations must be controlled. [...] However, in pure functional languages [...] maintaining correct I/O behaviour is non-trivial [...] as a programmer needs always to be considering how something will be executed [...] a task from which functional programming is usually claimed to relieve the programmer.

The implementation of practical functional programming languages, Nigel Perry (page 18 0f 144, in footnote).


A straightforward example of such a problematical application is that of a function which could allow us to interactively query and modify a database; this is clearly an interactive problem, since we may only be able to formulate queries once we have seen the responses to earlier ones.

Functional Programming and Operating Systems, Simon B. Jones and A. F. Sinclair (first page).


At present most declarative languages are guest languages on [...] procedural machines, and able to preserve their data in the file system provided by the host machine. However, the interface to the file system that is provided by the guest languages is primitive and often not referentially transparent.

A Functional Database, Phil Trinder (page 14 of 210).


Is there any hope of achieving purely functional, yet universal, and of course efficient I/O?

On the Expressiveness of Purely Functional I/O Systems, Paul Hudak and Raman S. Sundaresh (page 2 of 28).


[...] many I/O schemes have been proposed for purely functional languages, but they tend to be ad hoc in the sense of being designed to express particular kinds of I/O, without aiming for universal power.

PFL+: a kernel scheme for functional I/O, Andrew Gordon (page 4 of 28).


Functional languages are extremely powerful and succinct tools for expressing algorithms, but the way in which the results of such calculations should be communicated to the outside world is not obvious.

Message-based functional operating systems, Willian Stoye (first page).


The primary limitation of FP systems is that they are not history sensitive. Therefore they must be extended somehow before they can become practically useful.

Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs, John Backus (page 11 of 29).