From d1953891029a71115ee572b7b3798072cbaf2ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matth=C3=ADas=20P=C3=A1ll=20Gissurarson?= Date: Sat, 12 Mar 2016 00:59:51 +0100 Subject: Added exception handling with Alternative constraint according to spec. --- Data/GraphQL/Error.hs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 Data/GraphQL/Error.hs (limited to 'Data/GraphQL/Error.hs') diff --git a/Data/GraphQL/Error.hs b/Data/GraphQL/Error.hs new file mode 100644 index 0000000..25632b4 --- /dev/null +++ b/Data/GraphQL/Error.hs @@ -0,0 +1,62 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE OverloadedStrings #-} +module Data.GraphQL.Error ( + parseError, + CollectErrsT, + addErr, + addErrMsg, + runCollectErrs, + joinErrs, + errWrap + ) where + +import qualified Data.Aeson as Aeson +import Data.Text (Text, pack) + +import Control.Arrow ((&&&)) + +#if !MIN_VERSION_base(4,8,0) +import Control.Applicative (Applicative, pure) +import Data.Foldable (Foldable, concatMap) +import Prelude hiding (concatMap) +#endif + +-- | Wraps a parse error into a list of errors. +parseError :: Applicative f => String -> f Aeson.Value +parseError s = + pure $ Aeson.object [("errors", Aeson.toJSON [makeErrorMsg $ pack s])] + +-- | A wrapper for an applicative functor, for passing around error messages. +type CollectErrsT f a = f (a,[Aeson.Value]) + +-- | Takes a (wrapped) list (foldable functor) of values and errors and +-- joins the values into a list and concatenates the errors. +joinErrs + :: (Functor m, Functor f, Foldable f) + => m (f (a,[Aeson.Value])) -> CollectErrsT m (f a) +joinErrs = fmap $ fmap fst &&& concatMap snd + +-- | Wraps the given applicative to handle errors +errWrap :: Functor f => f a -> f (a, [Aeson.Value]) +errWrap = fmap (flip (,) []) + +-- | Adds an error to the list of errors. +addErr :: Functor f => Aeson.Value -> CollectErrsT f a -> CollectErrsT f a +addErr v = (fmap . fmap) (v :) + +makeErrorMsg :: Text -> Aeson.Value +makeErrorMsg s = Aeson.object [("message",Aeson.toJSON s)] + +-- | Convenience function for just wrapping an error message. +addErrMsg :: Functor f => Text -> CollectErrsT f a -> CollectErrsT f a +addErrMsg = addErr . makeErrorMsg + +-- | Runs the given query computation, but collects the errors into an error +-- list, which is then sent back with the data. +runCollectErrs :: Functor f => CollectErrsT f Aeson.Value -> f Aeson.Value +runCollectErrs = fmap finalD + where finalD (dat,errs) = + Aeson.object $ + if null errs + then [("data",dat)] + else [("data",dat),("errors",Aeson.toJSON $ reverse errs)] -- cgit v1.2.3