this post was submitted on 15 Feb 2024
10 points (100.0% liked)
Functional Programming
1398 readers
1 users here now
founded 1 year ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
view the rest of the comments
For IO, you really can't. Haskell uses a conceit that your program is a functional state transformer that operates on the contents of the RealWorld (there is an actual object of type RealWorld in the GHC runtime). The idea is that your program's input is a RealWorld state which contains you looking at a blank screen, and its output is a state where your screen says "hello world". There are no side effects, just an input and an output. This transformer is then handed off to the runtime which is seen as a simple imperative interpreter separate from Haskell. But of course, under the hood, the above scheme (the "IO Monad") is just an imperative sub-language within Haskell, whose effectfulness is kept contained by the type system.
For pure computation things are different, and you use a different set of idioms and data structures than imperative programmers are used to. A familiar example is using recursion instead of iteration. Less obvious is lookup structures: instead of hash tables (which you'd normally update imperatively) you use balanced tree structures where an "update" operation takes an old tree, and returns a new tree that shares most of its structure with the old one, with a few items changed. Then you rely on garbage collection to get rid of old items that are no longer reachable. There is an entire very good book "Purely Functional Data Structures" by Chris Okasaki, about such structures. The book is sort of old now, but still well worth reading.
For more about how effectfulness is actually handled in Haskell, see the article "Tackling the Awkward Squad" by Simon PJ, https://research.microsoft.com/en-us/um/people/simonpj/papers/marktoberdorf/mark.pdf .