{-# LANGUAGE CPP #-}
#if MIN_VERSION_base(4,9,0)
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
#endif

-- |
-- Module:
--   Reflex.FunctorMaybe
-- Description:
--   This module defines the FunctorMaybe class, which extends Functors with the
--   ability to delete values.
module Reflex.FunctorMaybe
  ( FunctorMaybe (..)
  ) where

import Data.IntMap (IntMap)
import Data.Map (Map)
#if !MIN_VERSION_base(4,16,0)
import Data.Semigroup (Option(..))
#endif
import Data.Witherable

--TODO: See if there's a better class in the standard libraries already

-- | A class for values that combines filtering and mapping using 'Maybe'.
-- Morally, @'FunctorMaybe' ~ KleisliFunctor 'Maybe'@.
{-# DEPRECATED FunctorMaybe "Use 'Filterable' from Data.Witherable instead" #-}
class FunctorMaybe f where
  -- | Combined mapping and filtering function.
  fmapMaybe :: (a -> Maybe b) -> f a -> f b

instance FunctorMaybe Maybe where
  fmapMaybe :: forall a b. (a -> Maybe b) -> Maybe a -> Maybe b
fmapMaybe = (a -> Maybe b) -> Maybe a -> Maybe b
forall a b. (a -> Maybe b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe

#if !MIN_VERSION_base(4,16,0)
deriving instance FunctorMaybe Option
#endif

instance FunctorMaybe [] where
  fmapMaybe :: forall a b. (a -> Maybe b) -> [a] -> [b]
fmapMaybe = (a -> Maybe b) -> [a] -> [b]
forall a b. (a -> Maybe b) -> [a] -> [b]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe

instance FunctorMaybe (Map k) where
  fmapMaybe :: forall a b. (a -> Maybe b) -> Map k a -> Map k b
fmapMaybe = (a -> Maybe b) -> Map k a -> Map k b
forall a b. (a -> Maybe b) -> Map k a -> Map k b
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe

instance FunctorMaybe IntMap where
  fmapMaybe :: forall a b. (a -> Maybe b) -> IntMap a -> IntMap b
fmapMaybe = (a -> Maybe b) -> IntMap a -> IntMap b
forall a b. (a -> Maybe b) -> IntMap a -> IntMap b
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe