Revision e061eb16

b/src/Ganeti/BasicTypes.hs
27 27
  , Result
28 28
  , ResultT(..)
29 29
  , resultT
30
  , FromString(..)
30
  , Error(..) -- re-export from Control.Monad.Error
31 31
  , isOk
32 32
  , isBad
33 33
  , justOk
......
74 74
-- | Type alias for a string Result.
75 75
type Result = GenericResult String
76 76

  
77
-- | Type class for things that can be built from strings.
78
class FromString a where
79
  mkFromString :: String -> a
80

  
81
-- | Trivial 'String' instance; requires FlexibleInstances extension
82
-- though.
83
instance FromString [Char] where
84
  mkFromString = id
85

  
86 77
-- | 'Monad' instance for 'GenericResult'.
87
instance (FromString a) => Monad (GenericResult a) where
78
instance (Error a) => Monad (GenericResult a) where
88 79
  (>>=) (Bad x) _ = Bad x
89 80
  (>>=) (Ok x) fn = fn x
90 81
  return = Ok
91
  fail   = Bad . mkFromString
82
  fail   = Bad . strMsg
92 83

  
93 84
instance Functor (GenericResult a) where
94 85
  fmap _ (Bad msg) = Bad msg
95 86
  fmap fn (Ok val) = Ok (fn val)
96 87

  
97
instance (FromString a, Monoid a) => MonadPlus (GenericResult a) where
98
  mzero = Bad $ mkFromString "zero Result when used as MonadPlus"
88
instance (Error a, Monoid a) => MonadPlus (GenericResult a) where
89
  mzero = Bad $ strMsg "zero Result when used as MonadPlus"
99 90
  -- for mplus, when we 'add' two Bad values, we concatenate their
100 91
  -- error descriptions
101
  (Bad x) `mplus` (Bad y) = Bad (x `mappend` mkFromString "; " `mappend` y)
92
  (Bad x) `mplus` (Bad y) = Bad (x `mappend` strMsg "; " `mappend` y)
102 93
  (Bad _) `mplus` x = x
103 94
  x@(Ok _) `mplus` _ = x
104 95

  
105
instance (FromString a) => MonadError a (GenericResult a) where
96
instance (Error a) => MonadError a (GenericResult a) where
106 97
  throwError = Bad
107 98
  catchError x h = genericResult h (const x) x
108 99

  
......
112 103
  _       <*> (Bad x) = Bad x
113 104
  (Ok f)  <*> (Ok x)  = Ok $ f x
114 105

  
115
instance (FromString a, Monoid a) => Alternative (GenericResult a) where
106
instance (Error a, Monoid a) => Alternative (GenericResult a) where
116 107
  empty = mzero
117 108
  (<|>) = mplus
118 109

  
......
135 126
instance (Monad f) => Functor (ResultT a f) where
136 127
  fmap f = ResultT . liftM (fmap f) . runResultT
137 128

  
138
instance (Monad m, FromString a) => Applicative (ResultT a m) where
129
instance (Monad m, Error a) => Applicative (ResultT a m) where
139 130
  pure = return
140 131
  (<*>) = ap
141 132

  
142
instance (Monad m, FromString a) => Monad (ResultT a m) where
143
  fail err = ResultT (return . Bad $ mkFromString err)
133
instance (Monad m, Error a) => Monad (ResultT a m) where
134
  fail err = ResultT (return . Bad $ strMsg err)
144 135
  return   = lift . return
145 136
  (>>=)    = flip (elimResultT throwError)
146 137

  
147
instance (Monad m, FromString a) => MonadError a (ResultT a m) where
138
instance (Monad m, Error a) => MonadError a (ResultT a m) where
148 139
  throwError = resultT . Bad
149 140
  catchError x h = elimResultT h return x
150 141

  
151 142
instance MonadTrans (ResultT a) where
152 143
  lift = ResultT . liftM Ok
153 144

  
154
instance (MonadIO m, FromString a) => MonadIO (ResultT a m) where
145
instance (MonadIO m, Error a) => MonadIO (ResultT a m) where
155 146
  liftIO = lift . liftIO
156 147

  
157
instance (Monad m, FromString a, Monoid a) => MonadPlus (ResultT a m) where
148
instance (Monad m, Error a, Monoid a) => MonadPlus (ResultT a m) where
158 149
  mzero = ResultT $ return mzero
159 150
  -- Ensure that 'y' isn't run if 'x' contains a value. This makes it a bit
160 151
  -- more complicated than 'mplus' of 'GenericResult'.
161 152
  mplus x y = elimResultT combine return x
162 153
    where combine x' = ResultT $ liftM (mplus (Bad x')) (runResultT y)
163 154

  
164
instance (Monad m, FromString a, Monoid a) => Alternative (ResultT a m) where
155
instance (Monad m, Error a, Monoid a) => Alternative (ResultT a m) where
165 156
  empty = mzero
166 157
  (<|>) = mplus
167 158

  
b/src/Ganeti/Errors.hs
40 40
  , maybeToError
41 41
  ) where
42 42

  
43
import Control.Monad.Error (Error(..))
44 43
import Text.JSON hiding (Result, Ok)
45 44
import System.Exit
46 45

  
......
113 112
  ])
114 113

  
115 114
instance Error GanetiException where
116
  strMsg = mkFromString
115
  strMsg = GenericError
117 116

  
118 117
instance JSON GanetiException where
119 118
  showJSON = saveGanetiException
120 119
  readJSON = loadGanetiException
121 120

  
122
instance FromString GanetiException where
123
  mkFromString = GenericError
124

  
125 121
-- | Error monad using 'GanetiException' type alias.
126 122
type ErrorResult = GenericResult GanetiException
127 123

  
b/src/Ganeti/HTools/Types.hs
367 367
-- will instead raise an exception.
368 368
type OpResult = GenericResult FailMode
369 369

  
370
-- | 'FromString' instance for 'FailMode' designed to catch unintended
370
-- | 'Error' instance for 'FailMode' designed to catch unintended
371 371
-- use as a general monad.
372
instance FromString FailMode where
373
  mkFromString v = error $ "Programming error: OpResult used as generic monad"
374
                           ++ v
372
instance Error FailMode where
373
  strMsg v = error $ "Programming error: OpResult used as generic monad" ++ v
375 374

  
376 375
-- | Conversion from 'OpResult' to 'Result'.
377 376
opToResult :: OpResult a -> Result a

Also available in: Unified diff