Rework exit model
[ganeti-local] / htools / Ganeti / BasicTypes.hs
1 {-
2
3 Copyright (C) 2009, 2010, 2011, 2012 Google Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19
20 -}
21
22 module Ganeti.BasicTypes
23   ( Result(..)
24   , isOk
25   , isBad
26   , eitherToResult
27   , annotateResult
28   , annotateIOError
29   ) where
30
31 import Control.Monad
32
33 -- | This is similar to the JSON library Result type - /very/ similar,
34 -- but we want to use it in multiple places, so we abstract it into a
35 -- mini-library here.
36 --
37 -- The failure value for this monad is simply a string.
38 data Result a
39     = Bad String
40     | Ok a
41     deriving (Show, Read, Eq)
42
43 instance Monad Result where
44   (>>=) (Bad x) _ = Bad x
45   (>>=) (Ok x) fn = fn x
46   return = Ok
47   fail = Bad
48
49 instance MonadPlus Result where
50   mzero = Bad "zero Result when used as MonadPlus"
51   -- for mplus, when we 'add' two Bad values, we concatenate their
52   -- error descriptions
53   (Bad x) `mplus` (Bad y) = Bad (x ++ "; " ++ y)
54   (Bad _) `mplus` x = x
55   x@(Ok _) `mplus` _ = x
56
57 -- | Simple checker for whether a 'Result' is OK.
58 isOk :: Result a -> Bool
59 isOk (Ok _) = True
60 isOk _ = False
61
62 -- | Simple checker for whether a 'Result' is a failure.
63 isBad :: Result a  -> Bool
64 isBad = not . isOk
65
66 -- | Converter from Either String to 'Result'.
67 eitherToResult :: Either String a -> Result a
68 eitherToResult (Left s) = Bad s
69 eitherToResult (Right v) = Ok v
70
71 -- | Annotate a Result with an ownership information.
72 annotateResult :: String -> Result a -> Result a
73 annotateResult owner (Bad s) = Bad $ owner ++ ": " ++ s
74 annotateResult _ v = v
75
76 -- | Annotates and transforms IOErrors into a Result type. This can be
77 -- used in the error handler argument to 'catch', for example.
78 annotateIOError :: String -> IOError -> IO (Result a)
79 annotateIOError description exc =
80   return . Bad $ description ++ ": " ++ show exc