-------------------------------------------------------------------------------- -- Copyright © 2015 Nikita Volkov -- Copyright © 2018 Remy Goldschmidt -- Copyright © 2019 chessai -- -- Permission is hereby granted, free of charge, to any person -- obtaining a copy of this software and associated documentation -- files (the "Software"), to deal in the Software without -- restriction, including without limitation the rights to use, -- copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the -- Software is furnished to do so, subject to the following -- conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -- OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- {-# OPTIONS_GHC -Wall #-} -------------------------------------------------------------------------------- {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE InstanceSigs #-} -------------------------------------------------------------------------------- -- | This module is defined internally to avoid using the 'these' -- package, which brings in a lot of very heavy and unnecessary -- transitive dependencies. We export the type and constructors -- here, in case a user should need it. -- We provide a small API for working with the 'These' type here. -- If one should need a fuller API, see https://hackage.haskell.org/package/these -- Converting to/from the two types should be trivial, as the -- data constructors are exported from both. module Refined.These ( -- * 'These' type These(This, That, These) -- * Consumption , these , fromThese , mergeThese , mergeTheseWith -- * Traversals , here, there -- * Case selections , justThis , justThat , justThese , catThis , catThat , catThese , partitionThese -- * Case predicates , isThis , isThat , isThese -- * Map operations , mapThese , mapThis , mapThat ) where -------------------------------------------------------------------------------- import Control.DeepSeq (NFData(rnf)) #if MIN_VERSION_base(4,10,0) import Data.Bifoldable (Bifoldable(bifold, bifoldr, bifoldl)) #endif #if MIN_VERSION_base(4,8,0) import Data.Bifunctor (Bifunctor(bimap, first, second)) #endif import Data.Data (Data) import Data.Maybe (isJust, mapMaybe) import Data.Semigroup (Semigroup((<>))) import Data.Typeable (Typeable) import GHC.Generics (Generic, Generic1) -- | This is defined internally to avoid using the 'these' -- package, which brings in a lot of very heavy and unnecessary -- transitive dependencies. We export the type and constructors -- here, in case a user should need it. data These a b = This a | That b | These a b deriving (Eq, Ord, Read, Show, Typeable, Data, Generic, Generic1) -- | Case analysis for the 'These' type. these :: (a -> c) -> (b -> c) -> (a -> b -> c) -> These a b -> c these l _ _ (This a) = l a these _ r _ (That x) = r x these _ _ lr (These a x) = lr a x -- | Takes two default values and produces a tuple. fromThese :: a -> b -> These a b -> (a, b) fromThese _ x (This a ) = (a, x) fromThese a _ (That x ) = (a, x) fromThese _ _ (These a x) = (a, x) -- | Coalesce with the provided operation. mergeThese :: (a -> a -> a) -> These a a -> a mergeThese = these id id -- | BiMap and coalesce results with the provided operation. mergeTheseWith :: (a -> c) -> (b -> c) -> (c -> c -> c) -> These a b -> c mergeTheseWith f g op t = mergeThese op $ mapThese f g t -- | A @Traversal@ of the first half of a 'These', suitable for use with @Control.Lens@. here :: (Applicative f) => (a -> f b) -> These a t -> f (These b t) here f (This x) = This <$> f x here f (These x y) = flip These y <$> f x here _ (That x) = pure (That x) -- | A @Traversal@ of the second half of a 'These', suitable for use with @Control.Lens@. there :: (Applicative f) => (a -> f b) -> These t a -> f (These t b) there _ (This x) = pure (This x) there f (These x y) = These x <$> f y there f (That x) = That <$> f x -- | @'justThis' = 'these' 'Just' (\_ -> 'Nothing') (\_ _ -> 'Nothing')@ justThis :: These a b -> Maybe a justThis = these Just (\_ -> Nothing) (\_ _ -> Nothing) -- | @'justThat' = 'these' (\_ -> 'Nothing') 'Just' (\_ _ -> 'Nothing')@ justThat :: These a b -> Maybe b justThat = these (\_ -> Nothing) Just (\_ _ -> Nothing) -- | @'justThese' = 'these' (\_ -> 'Nothing') (\_ -> 'Nothing') (\a b -> 'Just' (a, b))@ justThese :: These a b -> Maybe (a, b) justThese = these (\_ -> Nothing) (\_ -> Nothing) (\a b -> Just (a, b)) isThis, isThat, isThese :: These a b -> Bool -- | @'isThis' = 'isJust' . 'justThis'@ isThis = isJust . justThis -- | @'isThat' = 'isJust' . 'justThat'@ isThat = isJust . justThat -- | @'isThese' = 'isJust' . 'justThese'@ isThese = isJust . justThese -- | 'Bifunctor' map. mapThese :: (a -> c) -> (b -> d) -> These a b -> These c d mapThese f _ (This a ) = This (f a) mapThese _ g (That x) = That (g x) mapThese f g (These a x) = These (f a) (g x) -- | @'mapThis' = over 'here'@ mapThis :: (a -> c) -> These a b -> These c b mapThis f = mapThese f id -- | @'mapThat' = over 'there'@ mapThat :: (b -> d) -> These a b -> These a d mapThat f = mapThese id f -- | Select all 'This' constructors from a list. catThis :: [These a b] -> [a] catThis = mapMaybe justThis -- | Select all 'That' constructors from a list. catThat :: [These a b] -> [b] catThat = mapMaybe justThat -- | Select all 'These' constructors from a list. catThese :: [These a b] -> [(a, b)] catThese = mapMaybe justThese -- | Select each constructor and partition them into separate lists. partitionThese :: [These a b] -> ( [(a, b)], ([a], [b]) ) partitionThese [] = ([], ([], [])) partitionThese (These x y:xs) = first ((x, y):) $ partitionThese xs partitionThese (This x :xs) = second (first (x:)) $ partitionThese xs partitionThese (That y:xs) = second (second (y:)) $ partitionThese xs instance (Semigroup a, Semigroup b) => Semigroup (These a b) where This a <> This b = This (a <> b) This a <> That y = These a y This a <> These b y = These (a <> b) y That x <> This b = These b x That x <> That y = That (x <> y) That x <> These b y = These b (x <> y) These a x <> This b = These (a <> b) x These a x <> That y = These a (x <> y) These a x <> These b y = These (a <> b) (x <> y) #if MIN_VERSION_base(4,8,0) instance Bifunctor These where bimap :: (a -> c) -> (b -> d) -> These a b -> These c d bimap f _ (This a ) = This (f a) bimap _ g (That b) = That (g b) bimap f g (These a b) = These (f a) (g b) first :: (a -> c) -> These a b -> These c b first f = bimap f id second :: (b -> d) -> These a b -> These a d second f = bimap id f #endif instance Functor (These a) where fmap _ (This x) = This x fmap f (That y) = That (f y) fmap f (These x y) = These x (f y) instance Semigroup a => Applicative (These a) where pure = That This a <*> _ = This a That _ <*> This b = This b That f <*> That x = That (f x) That f <*> These b x = These b (f x) These a _ <*> This b = This (a <> b) These a f <*> That x = These a (f x) These a f <*> These b x = These (a <> b) (f x) instance Semigroup a => Monad (These a) where return = pure This a >>= _ = This a That x >>= k = k x These a x >>= k = case k x of This b -> This (a <> b) That y -> These a y These b y -> These (a <> b) y instance (NFData a, NFData b) => NFData (These a b) where rnf (This a) = rnf a rnf (That b) = rnf b rnf (These a b) = rnf a `seq` rnf b instance Foldable (These a) where foldr _ z (This _) = z foldr f z (That x) = f x z foldr f z (These _ x) = f x z instance Traversable (These a) where traverse _ (This a ) = pure $ This a traverse f (That x) = That <$> f x traverse f (These a x) = These a <$> f x sequenceA (This a ) = pure $ This a sequenceA (That x) = That <$> x sequenceA (These a x) = These a <$> x #if MIN_VERSION_base(4,10,0) instance Bifoldable These where bifold = these id id mappend bifoldr f g z = these (`f` z) (`g` z) (\x y -> x `f` (y `g` z)) bifoldl f g z = these (z `f`) (z `g`) (\x y -> (z `f` x) `g` y) #endif