Difference between revisions of "Open research problems/The I/O quandary"

From HaskellWiki
Jump to: navigation, search
m
(Content relocated to "The I/O Problem")
(Tag: New redirect)
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
+
#redirect [[The I/O Problem]]
[...] we need to come up with better answers about how to interact with the world. The blanket answer of “just push the <code>IO</code> monad through the entire codebase” is not great for a number of reasons [...]
 
  
<tt>[https://discourse.haskell.org/t/using-unsafeperformio-safely/4146/47 Using <code>unsafePerformIO</code> safely], Victor Miraldo.</tt><!-- 2022 -->
+
[[Category:Pages to be removed]]
</div>
 
<br>
 
 
 
<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.
 
 
 
<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>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
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.
 
 
 
<tt>[https://myowenopinion.com/post/dev/functional-programming-is-a-leaky-abstraction Functional Programming Is a Leaky Abstraction], Owen Merkling.</tt>
 
<!-- 2020 -->
 
</div>
 
<br>
 
 
 
<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.
 
 
 
<tt>[https://discourse.haskell.org/t/trying-to-understand-the-io/1172/8 Trying to understand the <code>IO ()</code>], ''"belka"''.</tt><!-- 2020 -->
 
</div>
 
<br>
 
 
 
<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. [...]
 
 
 
<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 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
APIs that interact with the outside world are unpredictable and make it difficult to test and simulate code paths in our apps. Existing solutions to this problem are verbose and complicated, so let’s explore a simpler solution by embracing singletons and global mutation [...]
 
 
 
<tt>[https://www.pointfree.co/blog/posts/21-how-to-control-the-world How to Control the World], Brandon Williams.</tt><!-- 2018 -->
 
</div>
 
<br>
 
 
 
<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 [...]
 
 
 
<tt>[https://nickhu.co.uk/Monads.pdf Understanding Monads], Nick Hu.</tt><!-- 2016 -->
 
</div>
 
<br>
 
 
 
<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.
 
 
 
<tt>[https://crypto.stanford.edu/~blynn/haskell/io.html A Problem With I/O], Ben Lynn.</tt><!-- 2016 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
A long time ago we had an effect system and we made pure the default (since we didn’t want people accidentally leaving it out due to sloth) and we made the impure specifier a very small and reasonable keyword: <code>io</code>. It was still a heavy complexity bill (required a full extra dimension of subtyping, parametricity, etc.) and <i>still</i> had people breaking the rule with <code>unsafe</code>, which meant that the putative benefits like “can do compile time evaluation” or “can spread on a GPU” weren’t there anyways. And people couldn’t do simple things like “put a printf in here for logging” (much like in [Haskell]).
 
 
 
Eventually people just took to making everything <code>io</code>, at which point it was a noise word and we decided to remove it (along with <code>pred</code>, which just meant pure, [boolean], and tracked by the typestate layer).
 
 
 
<tt>[https://mail.mozilla.org/pipermail/rust-dev/2013-April/003926.html rust-dev: sub-grammar for range pattern constants?],
 
Graydon Hoare.</tt><!-- 2013 -->
 
</div>
 
<br>
 
 
 
<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.
 
 
 
<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>
 
<br>
 
 
 
<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 [...]
 
 
 
<tt>[https://www.owenstephens.co.uk/assets/static/research/masters_report.pdf Approaches to Functional I/O], Owen Stephens.</tt><!-- 2011 -->
 
</div>
 
<br>
 
 
 
<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.
 
 
 
<tt>[https://existentialtype.wordpress.com/2011/05/01/of-course-ml-has-monads Of Course ML Has Monads!], Robert Harper.</tt><!-- 2011 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
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.
 
 
 
[...]
 
 
 
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.
 
 
 
<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 -->
 
</div>
 
<br>
 
 
 
<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".
 
 
 
<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 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
Indeed, rather than being ill-suited to interaction, as is sometimes assumed, perhaps because of the somewhat arcane feel of techniques such as [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.9725&rep=rep1&type=pdf <i>monads</i>] for modelling effectful computation, the declarative paradigm – with a simple orthogonal extension to support interactivity – fits the abstract behaviour of interactive, stateful systems surprisingly well.
 
 
 
<tt>[https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.7225&rep=rep1&type=pdf Programming Languages For Interactive Computing], Roly Perera.</tt><!-- 2007 -->
 
</div>
 
<br>
 
 
 
<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.
 
 
 
<tt>[https://essay.utwente.nl/57287/1/scriptie_Rorije.pdf Input/Output in Functional Languages (Using Algebraic Union Types)], R.J. Rorije.</tt><!-- 2006 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
[...] 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 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
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.
 
 
 
<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 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
We have always felt it as a nuisance of existing approaches that making such ‘state transformations’ interactive forces the programmer to change the program in a considerable way.
 
 
 
<tt>[https://maartenfokkinga.github.io/utwente/mmf2001c.pdf An alternative approach to I/O], Maarten Fokkinga and Jan Kuper.</tt><!-- 2001 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
Ever since [http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf McCarthy] 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.</tt><!-- 1999 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
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.</tt><!-- 1998 -->
 
</div>
 
<br>
 
 
 
<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.
 
 
 
<tt>[https://core.ac.uk/download/pdf/293056217.pdf Interacting with Functional Languages], Duncan Sinclair.</tt><!-- 1997 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
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ß.</tt><!-- 1996 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
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 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
At present most declarative languages are guest lan­guages on [...] procedural  machines, and able to preserve their data in the file system provided by the host machine. However, the inter­face to the file system that is provided by the guest languages is primitive and often not referentially transparent.
 
 
 
<tt>[https://www.cs.ox.ac.uk/files/3404/PRG82.pdf A Functional Database], Phil Trinder.</tt><!-- 1989 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
[...] 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.</tt><!-- 1989 -->
 
</div>
 
<br>
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
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://core.ac.uk/download/pdf/82449736.pdf Message-based functional  operating systems], Willian Stoye.</tt><!-- 1986 -->
 
</div>
 
<br>
 
 
 
__TOC__
 
 
 
== The I/O problem is mathematical in origin ==
 
 
 
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">
 
In a preliminary sense, mathematics is abstract because it is studied using highly general and formal resources.
 
 
 
<tt>[https://iep.utm.edu/math-app The Applicability of Mathematics], from the [https://iep.utm.edu/ Internet Encyclopedia of Philosophy].</tt>
 
</div>
 
 
 
In particular, they abstract away from the presence of an outside environment. For programming languages based on one or more of these individual fields of study e.g:
 
 
 
* Haskell, Clean, Miranda<sup>(R)</sup>: higher-order functions,
 
* Prolog: first-order predicate logic,
 
* Mercury: both;
 
 
 
this raises the question of I/O and its observable effects:
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
The primary limitation of FP systems is that they are not history sensitive. Therefore they must be extended somehow before they can become [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.628.7053&rep=rep1&type=pdf 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>
 
</div>
 
<sup> </sup>
 
<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?
 
 
 
<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>
 
</div>
 
<sup> </sup>
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
Input/output is [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.13.9123&rep=rep1&type=pdf 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 [http://conal.net/blog/posts/the-c-language-is-purely-functional pure functional I/O] but still involve a sequence of actions.
 
 
 
<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>
 
 
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">
 
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> [https://core.ac.uk/download/pdf/214330064.pdf The Anatomy of Programming Languages], Alice E. Fischer and Frances S. Grodzinsky (emphasis added).</tt>
 
</div>
 
 
 
* 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 or Prolog.
 
 
 
* 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">
 
'''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 <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>
 
 
 
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. 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">
 
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>
 
</div>
 
 
 
== 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">
 
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.
 
 
 
<tt>[http://conal.net/blog/posts/can-functional-programming-be-liberated-from-the-von-neumann-paradigm Conal Elliott.]</tt>
 
</div>
 
 
 
because of how various other effects have already been moved out of languages and into their implementations:
 
 
 
<div style="border-left:1px solid lightgray; padding: 1em" alt="blockquote">
 
[...] 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). [...]
 
 
 
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>
 
 
 
There is an assumption here:
 
* 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).
 
 
 
...which is false:
 
* 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.
 
 
 
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. [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">
 
[...] 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.
 
</div>
 
 
 
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">
 
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.
 
 
 
<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>
 
</div>
 
 
 
=== Using more than one language ===
 
 
 
One suggestion is to ease the relocation of effects into the implementation by using a suitable imperative language:
 
 
 
<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:
 
 
 
* runtime building for …
 
* … mathematical programming languages
 
 
 
<tt>[https://www.haskellforall.com/2021/04/the-end-of-history-for-programming.html Gabriella Gonzalez].</tt>
 
</div>
 
 
 
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">
 
[...] 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>
 
</div>
 
 
 
== 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 [[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://www.f.waseda.jp/terauchi/papers/toplas-witness.pdf Witnessing Side Effects], Tachio Terauchi and Alex Aiken.
 
 
 
* [https://www.cs.bham.ac.uk/~udr/papers/assign.pdf Assignments for Applicative Languages], Vipin Swarup, Uday S. Reddy and Evan Ireland.
 
 
 
* [https://www.cs.bham.ac.uk/~udr/papers/imperative-functional.pdf Imperative Functional Programming], Uday S. Reddy.
 
 
 
* [https://core.ac.uk/download/pdf/82162724.pdf Functional Programming with Side Effects], Mark B. Josephs.
 
 
 
* [https://accu.org/index.php/journals/2199 On Zero-Side-Effect Interactive Programming, Actors, and FSMs], Sergey Ignatchenko.
 
 
 
* [https://www.cs.nott.ac.uk/~pszgmh/clairvoyant.pdf Call-by-Need Is Clairvoyant Call-by-Value], Jennifer Hackett and Graham Hutton.
 
 
 
* [https://academic.oup.com/comjnl/article-pdf/31/3/243/1157325/310243.pdf Nondeterminism with Referential Transparency in Functional Programming Languages], F. Warren Burton.
 

Latest revision as of 12:48, 31 May 2022

Redirect to: