packages feed

collect-errors-0.1.0.0: src/Control/CollectErrors/PreludeInstances.hs

module Control.CollectErrors.PreludeInstances where

import Prelude

import Text.Printf ( printf )

import Control.CollectErrors.Type
    ( CollectErrors(CollectErrors), CanBeErrors, lift, lift2 )


instance (CanBeErrors es, Eq v) => Eq (CollectErrors es v) where
  (==) = liftGotValues2 "(==)" (==)

instance (CanBeErrors es, Ord v) => Ord (CollectErrors es v) where
  compare = liftGotValues2 "compare" compare
  (<) = liftGotValues2 "(<)" (<)
  (<=) = liftGotValues2 "(<=)" (<=)
  (>) = liftGotValues2 "(>)" (>)
  (>=) = liftGotValues2 "(>=)" (>=)
  max = lift2 max
  min = lift2 min

instance (CanBeErrors es, Bounded v) => Bounded (CollectErrors es v) where
  minBound = pure minBound
  maxBound = pure maxBound

instance (CanBeErrors es, Enum v) => Enum (CollectErrors es v) where
  toEnum = pure . toEnum
  fromEnum = liftGotValue "fromEnum" fromEnum

instance (CanBeErrors es, Num v) => Num (CollectErrors es v) where
  fromInteger = pure . fromInteger
  (+) = lift2 (+)
  (-) = lift2 (-)
  (*) = lift2 (*)
  abs = lift abs
  negate = lift negate
  signum = lift signum

instance (CanBeErrors es, Real v) => Real (CollectErrors es v) where
  toRational = liftGotValue "toRational" toRational


{- Utilities -}

errorMissingValue :: (Show t, Monoid t) => String -> t -> t2
errorMissingValue label es = 
  error $ printf "Missing value in %s: %s" label (show es)

errorMissingValues :: (Show t, Monoid t) => String -> [t] -> t2
errorMissingValues label ess = 
  error $ printf "Missing value(s) in %s: %s" label (show $ mconcat ess)

liftGotValue :: (CanBeErrors es) => String -> (t1 -> t) -> CollectErrors es t1 -> t
liftGotValue _ op (CollectErrors (Just v1) _) = 
  op v1
liftGotValue label op (CollectErrors _ es1) = 
  errorMissingValue label es1

liftGotValues2 :: (CanBeErrors es) => String -> (t1 -> t2 -> t) -> CollectErrors es t1 -> CollectErrors es t2 -> t
liftGotValues2 _ op (CollectErrors (Just v1) _) (CollectErrors (Just v2) _) = 
  op v1 v2
liftGotValues2 label op (CollectErrors _ es1) (CollectErrors _ es2) = 
  errorMissingValues label [es1, es2]