Esiste un idioma di lettura all'interno di una monade:
readM :: (Monad m, Read a) => String -> m a
readM s | [x] <- [x | (x, "") <- reads s] = return x
-- or @[x] <- [x | (x, _) <- reads s] = return [email protected]
-- to allow the garbage at the end of parsed string
| otherwise = fail $ "Failed to parse: \"" ++ s ++ "\""
E 'pericoloso per la IO
monade:
> readM "CmdOther" :: IO Cmd
CmdOther
> readM "Cmd?Other" :: IO Cmd
*** Exception: user error (Failed to parse: "Cmd?Other")
perché fail
genera un'eccezione IOError
nel caso di IO
, che però , può essere gestito:
*Main> (readM "Cmd?Other" :: IO Cmd) `catch` const (return CmdOther)
CmdOther
e sicuro nel caso di Maybe
monade:
> readM "CmdOther" :: Maybe Cmd
Just CmdOther
> readM "Cmd?Other" :: Maybe Cmd
Nothing
perché fail
è const Nothing
in questo caso.
In ogni caso, se si desidera una funzione totale guiString2Cmd
con una firma String -> Cmd
si può scrivere come readM
:
guiString2Cmd :: String -> Cmd
guiString2Cmd s | [x] <- [x | (x, "") <- reads s] = x
| otherwise = CmdExit
e poi:
> guiString2Cmd "CmdOther"
CmdOther
> guiString2Cmd "Cmd?Other"
CmdExit
approccio leggermente più generico.
Per *
tipi:
class Failable0 t where
fail0 :: t
readG0 :: (Failable0 t, Read t) => String -> t
readG0 s | [x] <- [x | (x, "") <- reads s] = x
| otherwise = fail0
poi:
instance Failable0 Cmd where
fail0 = CmdExit
Per * -> *
tipi:
class Failable f where
fail :: String -> f a
class Functor f => Pointed f where
pure :: a -> f a
readG :: (Failable f, Pointed f, Read a) => String -> f a
readG s | [x] <- [x | (x, "") <- reads s] = pure x
| otherwise = fail $ "Failed to parse: \"" ++ s ++ "\""
Utilizzando letture potrebbe essere una migliore idea in realtà ... – mbrodersen
Sì, il migliore modo per gestire una pura eccezione è non generarlo in primo luogo. – dave4420
Per la cronologia, le eccezioni (comprese quelle generate da 'read') possono essere rilevate solo nella monade IO, utilizzando le funzioni fornite in' Control.Exception'. Non entrerò in ulteriori dettagli perché "legge" è una soluzione migliore. –