{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} module Shpadoinkle.Widgets.Types.Remote where import Control.Applicative import Data.Aeson (FromJSON, ToJSON) import GHC.Generics import Shpadoinkle (NFData) #ifdef TESTING import Test.QuickCheck (Arbitrary (..), elements) #endif data Remote e a = Success a | Failure e | Loading | NotAsked deriving (Eq, Ord, Show, Read, Generic, Functor, Foldable, Traversable, ToJSON, FromJSON, NFData) instance Applicative (Remote e) where pure = Success Success f <*> Success x = Success (f x) Failure e <*> _ = Failure e Loading <*> _ = Loading NotAsked <*> _ = NotAsked _ <*> Failure e = Failure e _ <*> Loading = Loading _ <*> NotAsked = NotAsked instance Alternative (Remote e) where empty = NotAsked x@(Success _) <|> _ = x NotAsked <|> x = x x <|> NotAsked = x _ <|> x = x instance Semigroup a => Semigroup (Remote e a) where Success x <> Success y = Success (x <> y) x <> y = x <|> y instance Semigroup a => Monoid (Remote e a) where mempty = empty instance Monad (Remote e) where Success a >>= f = f a Failure e >>= _ = Failure e NotAsked >>= _ = NotAsked Loading >>= _ = Loading #ifdef TESTING instance (Arbitrary e, Arbitrary a) => Arbitrary (Remote e a) where arbitrary = do (e, a) <- (,) <$> arbitrary <*> arbitrary elements [ Success a, Failure e, Loading, NotAsked ] #endif