Iniziamo con un pezzo di un codice più vasto e scorporato per quello che mi serve sapere.
- Codice:
-- questo è il file Cfg.hs
module Cfg where
import Control.Monad (liftM)
import Control.Conditional (ifM)
import System.Directory (doesFileExist)
import System.Environment.FindBin (getProgPath)
type Maybe2 a = (Maybe a, Maybe a)
getCfgs :: IO [Maybe2 String]
getCfgs = do
thisFile <- liftM (++ "/configs") getProgPath
ifM (doesFileExist thisFile)
(liftM (map chop . lines) (readFile thisFile))
(return [])
where
chop :: String -> Maybe2 String
chop str = case words str of
x:y:_ -> (Just x , Just y)
x:[] -> (Just x , Nothing)
_ -> (Nothing, Nothing)
getCfgValOf :: String -> IO (Maybe String)
getCfgValOf key = liftM h getCfgs
where
h :: [Maybe2 String] -> Maybe String
h [] = Nothing
h ((a, b):xs) | a == Just key = b
| otherwise = h xs
In realtà in questo caso non è cruciale sapere cose fanno le funzioni, piuttosto sapere i tipi delle cose.
Testo nascosto, fai click qui per vederlo
Comunque sia, per l'esempio, consideriamo un file chiamato config nella stessa cartella del progamma col main :: IO () come sotto1
- Codice:
GRUB_DEFAULT 0
GRUB_TIMEOUT_STYLE hidden
GRUB_TIMEOUT 0
GRUB_CMDLINE_LINUX_DEFAULT quiet
- Codice:
$ ghci
> :load Cfg.hs
> getCfgValOf "GRUB_TIMEOUT_STYLE"
Just "hidden"
> getCfgValOf "GRUB_CMDLINE_LINUX_DEFAULT"
Just "quiet"
Prendiamo un main così
- Codice:
import Cfg (getCfgValOf)
main :: IO ()
main = mapM printCfgValOf [ "GRUB_DEFAULT"
, "GRUB_TIMEOUT_STYLE"
, "GRUB_TIMEOUT"
, "GRUB_CMDLINE_LINUX_DEFAULT"
]
where printCfgValOf :: String -> IO ()
printCfgValOf key = print =<< getCfgValOf key
Mi chiedo che fine faccia quel getCfgs :: IO (Maybe2 String) richiamato da definizione dietro le quinte ben quattro volte consecutive. Mi sto riferendo a questo pezzo su Real World Haskell
What Is An I/O Action?
Actions:
[...]
* Produce an effect when performed, but not when evaluated. That is, they only produce an effect when called by something else in an I/O context.
[...]
Cosa fa il calcolatore? È un IO qualcosa, quindi da manuale dovrebbe aspettare di essere incastrato in un contesto I/O per fare un qualcosa: e questo qualcosa è restituire una particolare lista. Ma da una chiamata alla successiva che succede, viene rifatto di volta in volta tutto il computo che definisce getCfgs? Credo anche di non essere riuscito ad intendere perfettamente la differenza tra i due termini in corsivo in questo caso.
- Il contenuto è puramente casuale. ↑