Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've read a lot of books and articles about functional programming and still ashamed of not being able to understand for sure some very basic concepts.

One of the main ideas of functional programming is that same input always should produce same output. Therefore, say, querying database or writing file could not be done in a pure functional style by definition. That's for example, is one of reasons we need monads.

The question is - why we consider STDOUT output as something impure? Yes, any filehandler is risky - we never can be sure that data always will be written. But what about STDOUT? Why should we think of it as of something unreliable? Is it more unreliable that evaluation itself? I mean, we always can pull the trigger and thus, interrupt calculation.

share|improve this question

4 Answers 4

up vote 5 down vote accepted

Therefore, say, querying database or writing file could not be done in a pure functional style by definition. That's for example, is one of reasons we need monads.

Nobody "needs" monads, that's just one way to describe things. In fact, it's probably not even the best way. Some form of effect typing, uniqueness types, or a system based on full linear logic seem more persuasive in theory but are all more radical departures from well-known type systems and more complicated to express. Monadic IO as found in Haskell is a compromise between usability and simplicity, since it essentially models fully imperative programming in a way that coexisted easily with the existing ML-style type system already used in the language.

The question is - why we consider STDOUT output as something impure? Yes, any filehandler is risky - we never can be sure that data always will be written. But what about STDOUT? Why should we think of it as of something unreliable? Is it more unreliable that evaluation itself? I mean, we always can pull the trigger and thus, interrupt calculation.

It's not, and we don't. Input to, and output from, the program as a whole can be simply regarded as arguments and results from treating the entire program as one large pure function. As long as it prints the same thing to stdout if you feed it the same thing from stdin, it's still a pure function. In fact, before introducing monadic IO, Haskell used a stream-based I/O system that used pure lazy streams for input and output. It dropped it because it was apparently a pain to use, which may give you some idea of why you haven't heard of anything like this. :]

To make the point in a sillier way, consider the minimalist esoteric language, Lazy K:

Lazy K is a garbage-collected, referentially transparent functional programming language, with a simple stream-based I/O system.

What distinguishes Lazy K from other such languages is its almost total lack of other features. It does not, for example, offer an integrated Hindley-Milner polymorphic type system. It is not shipped with an extensive standard library with support for platform-independent GUI programming and bindings to other languages. Nor could any such library be written since, among other things, Lazy K does not provide any way to define or refer to any functions other than built-ins. This inability is complemented by a matching lack of support for numbers, strings, or any other data type. Nevertheless, Lazy K is Turing-complete.

(...)

Lazy K programs live in the same timeless Platonic realm as mathematical functions, what the Unlambda page calls "the blessed realm of the pure untyped lambda calculus." Just as garbage collection hides the process of memory management from the programmer, so referential transparency hides the process of evaluation. The fact that some calculation is necessary in order to view a picture of the Mandelbrot set, or in order to "run" a Lazy K program, is an implementation detail. That's the essence of functional programming.

(...)

How to handle input and output in a language without side effects? In a certain sense, input and output aren't side effects; they are, so to speak, front- and back-effects. So it is in Lazy K, where a program is simply treated as a function from the space of possible inputs to the space of possible outputs.

I doubt you'll find a more purely functional language than that!


Keep in mind, though, that the above applies only to essentially taking the input and output of a pure function and connecting them to stdin/stdout "externally" in some way. There's a big difference between that and having access to the real system-level I/O primitives. The implementation details of reading and writing to the streams may leak impurity unless carefully encapsulated.

I expect this is the main reason that you can't do this directly in Haskell--the sensible use cases are slim compared to using monadic IO, and for the latter there's a lot of benefit to having access to the real thing. I believe that's why, for instance, the command-line arguments to the program aren't simply passed as arguments to main, even though it seems intuitively that they should be.

You can recover a minimal version of something like this in a specific program, though--just capture the arguments as pure values and then use the interact function for the rest of your program.

share|improve this answer
    
Sir, I must confess, I enjoy any your answer on any of the stacks. You definitely should write a book Haskell and I am NOT kidding. –  shabunc Sep 15 '11 at 14:35
    
@shabunc: I've sometimes wondered how close the sum total of my answers on SO are to being the size of a book already... –  C. A. McCann Sep 15 '11 at 14:45
    
Could you give an example of a system based on full linear logic? That seems interesting, if it exists. –  configurator Sep 15 '11 at 17:42
    
@configurator: Notice how I linked to specific languages for the others, but a wikipedia page for linear logic? Alas, if I had an example, I would have given it. :[ All I've heard of are partial prototypes and experimental systems from CS research. If you want to dig deeper into that, here's some relatively approachable material on linear type systems that might get you started. –  C. A. McCann Sep 15 '11 at 19:10
    
Thanks for the link. I'll take a look. –  configurator Sep 15 '11 at 20:22

While purity in a functional program is a worthy goal, the reality is that every non-trivial, useful program will have some impurity (or "side effects"), for the reasons you mentioned.

Completely pure programs are, by definition, a sealed black box, and are essentially uninteresting.

The functional language Haskell takes care of this problem by isolating side effects such as output in monads. The monad preserves a purely functional style of programming, while still making it possible to produce output.

share|improve this answer
    
sure, you are right. But I understand why 100% pureness is utopia. I question is just about STDOUT. –  shabunc Sep 15 '11 at 14:03
1  
STDOUT is a side effect, just like any other. Internally, the monad would perform any error checking that might be required. –  Robert Harvey Sep 15 '11 at 14:06
    
yes, it IS what this question is about - why it considered to be side effect just like any other? –  shabunc Sep 15 '11 at 14:07
2  
Anything that modifies the outside world is considered a side effect. –  Robert Harvey Sep 15 '11 at 14:10

Writing to STDOUT can fail if you're not connected to a terminal device, or if you (for some reason) closed the file-descriptor for it.

Also, STDOUT is not always "the console screen". Sometimes it's piped to another program. Sometimes the pipe is broken.

share|improve this answer

It helps if you think of purity in terms "Changes the state of the outside world". That could include writing to a console, log file, ejecting the CD or "Launching the Missiles".

It also can be an issue in terms of concurrent execution. If you know a function has no side effects you can easily arrange for concurrency as you can prove that there can be no race conditions or the like.

share|improve this answer
    
Changes the state of the outside world or depends on the state of the outside world. See this question for more discussion along these lines. –  MatrixFrog Sep 18 '11 at 22:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.