I’ll answer a few of your questions, then provide some links.
Answers
-
How do i understand the ‘source’ of the mutability in Haskell?
Mutability in Haskell uses the same mechanism as C, usually because:
-
the run-time system for Haskell, and
-
the primitive entities Haskell is based on (e.g. the
Integer
type and its arithmetic operatorsprimPlusInteger
,primMinusInteger
, etc)
are written in an imperative language like C.
-
-
Is everything written in Haskell?
No. That would be impractical - that’s why Haskell has an FFI.
-
How do i know if something is mutable?
Sometimes by looking at the name of the type e.g.
IORef
,STRef
,MVar
,STMVar
. But there’s no way in general to know if something in Haskell is mutable. -
What does the Haskell runtime do when it runs the program?
The Haskell run-time system is “dual-purpose”:
-
it can call regular Haskell functions like
(\ x y -> x && not y)
; -
and run
IO
actions likeputStrLn "Hello, World!"
.
You can see this in the type signature for
IO
’s bind operator:(>>=) :: IO a -- run this action to obtain a result, -> (a -> IO b) -- then call this function, using the result as the argument, -> IO b -- to build another action.
What the run-time system selects then depends on what it’s presented with moment-to-moment as the Haskell program runs.
-
-
[…] I am naturally left to wonder how [Haskell] actually interacts with the outside world.
Without going into all the possible ways
IO
can be implemented: very carefully! There are good reasons why the Haskell 2010 report (page 95 of 329) deemsIO
to be abstract, so until that requirement changes (e.g. in a future version of Haskell) I recommend either:-
ignoring how
IO
is implemented altogether - so far, you’ve managed to get by without wondering how(->)
is implemented; -
or looking at several implementations of
IO
e.g. in How to Declare an Imperative to better understand the advantages and difficulties of each implementation method.
-
Links
From the wiki: