Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is accessing System.Info not considered an IO operation in Haskell?

Tags:

In the module System.Info I see these functions:

os :: String arch :: String compilerName :: String compilerVersion :: Version 

Why is there no IO there? They are accessing the system... Am I wrong? My expectation was something like:

os :: IO String arch :: IO String compilerName :: IO String compilerVersion :: IO Version 

Use case:

      print os            -- "darwin"       print arch          -- "x86_64"       print compilerName  -- "ghc" 
like image 615
Francisco Albert Avatar asked Nov 18 '19 20:11

Francisco Albert


People also ask

What is IO () Haskell?

IO is the way how Haskell differentiates between code that is referentially transparent and code that is not. IO a is the type of an IO action that returns an a . You can think of an IO action as a piece of code with some effect on the real world that waits to get executed.

How is Haskell IO pure?

Haskell is a pure language and even the I/O system can't break this purity. Being pure means that the result of any function call is fully determined by its arguments. Procedural entities like rand() or getchar() in C, which return different results on each call, are simply impossible to write in Haskell.

What is an IO string?

An IO String is a String in the IO-Monad. If a function in the IO-Monad returns an IO String, you get the String by doing: do str <- ioFunc. A function is in the IO-Monad when it needs IO-access and has to return IO types.


2 Answers

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.

like image 192
chepner Avatar answered Oct 13 '22 04:10

chepner


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.

like image 37
Carl Avatar answered Oct 13 '22 04:10

Carl