Why is accessing System.Info not considered an IO operation in Haskell?
The question is a good one. The answer, such as it is, is that those values are static per program compilation. They are essentially compiled into the program, and never change after that. As such, nothing (in the assumptions GHC uses) breaks if you treat them as constants. And it's more convenient to use a simple constant than an IO action.
But that's all sort of legacy reasoning. Haskell is an old language. (No really, it's older than Java by several years.) A lot of libraries have been built with reasoning that is no longer considered best practices. These are examples of that. A modern library exposing them would probably make them IO actions even though the results don't change after compilation. It's more useful to put things that aren't constants at the source level behind IO actions, though there are still some notable exceptions, like Int
changing size between 32- and 64-bit platforms.
In any case... I'd say your expectations are solid, and those types are the results of historical oddities.
You aren't getting that information at runtime. They are hardcoded in the compiler as installed on your system.
This is most obvious if you look at the definition for compilerName
as found in http://hackage.haskell.org/package/base-4.12.0.0/docs/src/System.Info.html.
compilerName :: String
compilerName = "ghc"
but even something like os
os :: String
os = HOST_OS
is defined in terms of an otherwise undefined name HOST_OS
(a value starting with an uppercase letter??) which suggests that is just a placeholder which gets replaced during installation.
Someone can also correct me (please!), but the {-# LANGUAGE CPP #-}
pragma at the top of that file suggests that HOST_OS
and the like are replaced by appropriate strings by the C preprocessor before compilation.