module Data.SVG.Internal.Fail where

import Control.Applicative
import Control.Monad
import Data.Maybe (listToMaybe)

data FailM a = Fail String | OK a

instance Functor FailM where
  fmap _ (Fail x) = Fail x
  fmap f (OK x) = OK (f x)

instance Monad FailM where
  return = OK
  fail = Fail
  (>>=) (Fail x) _ = Fail x
  (>>=) (OK x) f = f x

instance Applicative FailM where
  (<*>) = ap
  pure = return

runFail :: FailM a -> Either String a
runFail (Fail x) = Left x
runFail (OK x) = Right x

maybeFail :: String -> Maybe a -> FailM a
maybeFail e = maybe (Fail e) OK

maybeRead :: Read a => String -> Maybe a
maybeRead = fmap fst . listToMaybe . reads