Perché l'accesso a System.Info non è considerato un'operazione di I / O in Haskell?


25

Nel modulo System.Infovedo queste funzioni:

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

Perché non IOc'è? Stanno accedendo al sistema ... Sbaglio? La mia aspettativa era qualcosa di simile:

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

Caso d'uso:

      print os            -- "darwin"
      print arch          -- "x86_64"
      print compilerName  -- "ghc"

Risposte:


29

Non stai ottenendo tali informazioni in fase di esecuzione . Sono codificati nel compilatore come installati sul sistema.

Questo è più ovvio se guardi la definizione di compilerNamecome si trova in http://hackage.haskell.org/package/base-4.12.0.0/docs/src/System.Info.html .

compilerName :: String
compilerName = "ghc"

ma anche qualcosa del genere os

os :: String
os = HOST_OS

è definito in termini di un nome altrimenti indefinito HOST_OS(un valore che inizia con una lettera maiuscola ??) che suggerisce che è solo un segnaposto che viene sostituito durante l'installazione.

Qualcuno può anche correggermi (per favore!), Ma il {-# LANGUAGE CPP #-}pragma nella parte superiore di quel file suggerisce che HOST_OSe simili sono sostituiti da stringhe appropriate dal preprocessore C prima della compilazione.


2
Se l'OP ne vuole davvero un po ' IO, c'è un wrapper uname(3)disponibile su Hackage: hackage.haskell.org/package/bindings-uname
thsutton

19

La domanda è buona. La risposta, come è, è che quei valori sono statici per la compilazione del programma. Sono essenzialmente compilati nel programma e non cambiano mai dopo. In quanto tale, nulla (nelle ipotesi utilizzate da GHC) si rompe se le trattate come costanti. Ed è più conveniente usare una costante semplice che un'azione IO.

Ma questo è tutto un ragionamento legacy. Haskell è una vecchia lingua. (No, in realtà è più vecchio di Java da diversi anni.) Molte librerie sono state costruite con ragionamenti che non sono più considerati best practice. Questi sono esempi di questo. Una moderna biblioteca che li espone probabilmente li renderebbe azioni IO anche se i risultati non cambiano dopo la compilazione. È più utile mettere le cose che non sono costanti a livello di sorgente dietro le azioni IO, anche se ci sono ancora alcune notevoli eccezioni, come Intcambiare le dimensioni tra piattaforme a 32 e 64 bit.

In ogni caso ... direi che le tue aspettative sono solide e quei tipi sono il risultato di stranezze storiche.


-9

EDIT: Grazie a @interjay e @Antal Spector-Zabusky per aver spiegato il motivo per cui questa risposta è stata annullata. Scrissero

La documentazione è un po 'fuorviante. I valori sono codificati nel compilatore GHC. Dopo 48 anni saprai sicuramente che il codice attuale supera sempre la documentazione. - interjay ieri @ andy256 Hai perfettamente ragione sul fatto che la documentazione non è buona (in effetti, questo fa parte del motivo per cui Francisco ha posto questa domanda in primo luogo) e la tua confusione è comprensibile. La cosa su Haskell è che se quei valori di String potrebbero variare in fase di esecuzione, sarebbe un bug egregio - le variabili non possono cambiare. Questo è il significato del costruttore del tipo IO: rappresenta un calcolo a cui è consentito accedere al "mondo esterno", e quindi uno il cui risultato può cambiare. Effettuare una chiamata di sistema è un buon esempio di azione IO. ... [1/2] - Antal Spector-Zabusky 9 ore fa @ andy256 ... (Un'altra azione IO potrebbe essere "l'aggiornamento di un contatore globale".) Quindi quando vediamo una stringa, sappiamo che non può essere in comunicazione con il sistema operativo sotto il cofano. Questo è il motivo, forse sorprendentemente se non sei abituato a Haskell, non sarebbe facile implementare os :: String per fare una chiamata di sistema - un tale valore non è implementabile in Haskell di base, violerebbe le aspettative di ogni programmatore su come i programmi funziona e potenzialmente fa scattare anche il compilatore e l'ottimizzatore (non una preoccupazione teorica: ci sono risposte Stack Overflow in cui le persone incontrano problemi analoghi). [2/2] - Antal Spector-Zabusky Questo è il motivo, forse sorprendentemente se non sei abituato a Haskell, non sarebbe facile implementare os :: String per fare una chiamata di sistema - un tale valore non è implementabile in Haskell di base, violerebbe le aspettative di ogni programmatore su come i programmi funziona e potenzialmente fa scattare anche il compilatore e l'ottimizzatore (non una preoccupazione teorica: ci sono risposte Stack Overflow in cui le persone incontrano problemi analoghi). [2/2] - Antal Spector-Zabusky Questo è il motivo, forse sorprendentemente se non sei abituato a Haskell, non sarebbe facile implementare os :: String per fare una chiamata di sistema - un tale valore non è implementabile in Haskell di base, violerebbe le aspettative di ogni programmatore su come i programmi funziona e potenzialmente fa scattare anche il compilatore e l'ottimizzatore (non una preoccupazione teorica: ci sono risposte Stack Overflow in cui le persone incontrano problemi analoghi). [2/2] - Antal Spector-Zabusky e potenzialmente anche far scattare il compilatore e l'ottimizzatore (non una preoccupazione teorica - ci sono risposte Stack Overflow in cui le persone incontrano problemi analoghi). [2/2] - Antal Spector-Zabusky e potenzialmente anche far scattare il compilatore e l'ottimizzatore (non una preoccupazione teorica - ci sono risposte Stack Overflow in cui le persone incontrano problemi analoghi). [2/2] - Antal Spector-Zabusky

Attualmente ha due voti per l'eliminazione. Lascerò che il processo segua il suo corso, ma suggerisco che abbia effettivamente un certo valore. In una nota a margine, le loro spiegazioni mostrano che la domanda era debole, così come le risposte, dal momento che un neofita di Haskell potrebbe facilmente seguire il ragionamento che ho fatto.

Risposta originale:

Non sono un programmatore Haskell, ma le due risposte già fornite non corrispondono alla documentazione collegata all'OP.

La mia interpretazione della documentazione segue.

os :: String - Questo ti dà "Il sistema operativo su cui è in esecuzione il programma."

Mi aspetto che questo emetta una chiamata di sistema per ottenere le informazioni. Poiché il sistema su cui viene compilato il programma potrebbe essere diverso da quello su cui viene eseguito, non può essere un valore inserito dal compilatore. Se il codice viene interpretato, l'interprete può fornire il risultato, che deve essere ottenuto tramite una chiamata di sistema.

arch :: String - Questo ti dà "L'architettura della macchina su cui è in esecuzione il programma".

Ancora una volta, mi aspetto che questo emetta una chiamata di sistema per ottenere le informazioni. Poiché il sistema su cui viene compilato il programma potrebbe essere diverso da quello su cui viene eseguito, non può essere un valore inserito dal compilatore.

compilerName :: String - Questo ti dà "L'implementazione di Haskell con la quale il programma è stato compilato o viene interpretato".

Questo valore viene sicuramente inserito dal compilatore / interprete.

compilerVersion :: String - Questo ti dà "La versione di compilerName con cui il programma è stato compilato o viene interpretato".

Questo valore viene sicuramente inserito dal compilatore / interprete.

Sebbene si possa considerare che le prime due chiamate ottengano input, il risultato deriva dai valori conservati dal sistema operativo. L'I / O si riferisce generalmente all'accesso alla memoria secondaria.


3
Non è vero per haskell. Qui eventuali calcoli non sono ordinati e il loro risultato può essere memorizzato nella cache. Le funzioni sono pure, quindi se una funzione non accetta argomenti, è molto simile a una costante. Le funzioni di un arg sembrano solo hashmaps o dizionari, che calcolano il valore in base alla chiave. Non è possibile utilizzare l'ambiente esterno, eseguire syscall in tali funzioni, non è nemmeno possibile ottenere un numero casuale o una data corrente. Ma se davvero vuoi usare quel "sequenziamento", o ambiente, allora devi usare la IOmonade per emulare lo stato, emulare la sequenza delle operazioni
Yuri Kovalenko,

"Non puoi usare un ambiente esterno, esegui syscall in tali funzioni" - Certo che puoi, specialmente se "tu" sei il compilatore di Haskell! Sarebbe molto facile implementare un'implementazione di Haskell in os :: Stringmodo che esegua una chiamata di sistema quando viene valutata.
Tanner Swett,

2
Non penso che tu capisca il significato della monade IO in Haskell.
Sneftel,

@Sneftel Hai, ovviamente, ragione. Ho scelto di rispondere perché dopo 48 anni di programmazione in ogni paradigma e dopo aver scritto lo strano compilatore, le risposte iniziali non corrispondevano alla documentazione, e ancora non lo fanno. Lo dice chiaramente ose archsono ottenuti in fase di esecuzione.
andy256,

1
La documentazione è un po 'fuorviante. I valori sono codificati nel compilatore GHC. Dopo 48 anni saprai sicuramente che il codice attuale supera sempre la documentazione.
interjay
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.