Since side-effects break referential transparency, don't they go against the point of functional languages?
相关问题
- What is the best way to do a search in a large fil
- In what practical case bool(std::ifstream) != std:
- Relation between Function1 and Reader Monad
- aio_write on linux with rtkaio is sometimes long
- scala passing function with underscore produces a
相关文章
- Is there something like the threading macro from C
- Learning F#: What books using other programming la
- Creating a list of functions using a loop in R
- Fastest way to create files in C#
- How can I resolve a relative path to absolute path
- What is the difference between `ioToST` and `unsaf
- Reader interface and the Read method in golang
- When to use interfaces, and when to use higher ord
There are several options available to handle I/O in a functional language.
There's a research dissertation that exhaustively analyses these.
Functional I/O is an ongoing field of research and there are other languages which address this issue in interesting and mind-mangling ways. Hoare logic is put to use in some research languages. Others (like Mercury) use uniqueness typing. Still others (like Clean) use effect systems. Of these I have a very, very limited exposure to Mercury only, so I can't really comment on details. There's a paper that details Clean's I/O system in depth, however, if you're interested in that direction.
To the best of my understanding, if you want to have side effects in a functional language, you have to code them explicitly.
There are two techniques that are used by purely functional programming languages to model side effects:
1) A world type that represents external state, where each value of that type is guaranteed by the type system to be used only once.
In a language that uses this approach the function
print
andread
might have the types(string, world) -> world
andworld -> (string, world)
respectively.They might be used like this:
But not like this:
(because w is used twice)
All built-in functions with side-effects would take and return a world value. Since all functions with side-effects are either built-ins or call other functions with side-effects, this means that all functions with side-effects need to take and return a world.
This way it is not possible to call a function with side-effects twice with the same arguments and referential transparency is not violated.
2) An IO monad where all operations with side effects have to be executed inside that monad.
With this approach all operations with side effects would have type
io something
. For exampleprint
would be a function with typestring -> io unit
andread
would have typeio string
.The only way to access the value of performing operation would be to use the "monadic bind" operation (called >>= in haskell for example) with the IO operation as one argument and a function describing what to do with the result as the other operand.
The example from above would look like this with monadic IO: