{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.Ext.Selectable
  ( Selectable (..),
    selectBy,
  )
where

import qualified Data.HashMap.Lazy as HM
import Data.Morpheus.Ext.Failure (Failure (..))
import Data.Morpheus.Ext.KeyOf (KeyOf (..))
import Relude

class Selectable k a c | c -> a where
  selectOr :: d -> (a -> d) -> k -> c -> d

  member :: k -> c -> Bool
  member = Bool -> (a -> Bool) -> k -> c -> Bool
forall k a c d. Selectable k a c => d -> (a -> d) -> k -> c -> d
selectOr Bool
False (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)

instance KeyOf k a => Selectable k a [a] where
  selectOr :: d -> (a -> d) -> k -> [a] -> d
selectOr d
fb a -> d
f k
key [a]
lib = d -> (a -> d) -> Maybe a -> d
forall b a. b -> (a -> b) -> Maybe a -> b
maybe d
fb a -> d
f ((a -> Bool) -> [a] -> Maybe a
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((k
key k -> k -> Bool
forall a. Eq a => a -> a -> Bool
==) (k -> Bool) -> (a -> k) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> k
forall k a. KeyOf k a => a -> k
keyOf) [a]
lib)

instance (Eq k, Hashable k) => Selectable k a (HashMap k a) where
  selectOr :: d -> (a -> d) -> k -> HashMap k a -> d
selectOr d
fb a -> d
f k
key HashMap k a
lib = d -> (a -> d) -> Maybe a -> d
forall b a. b -> (a -> b) -> Maybe a -> b
maybe d
fb a -> d
f (k -> HashMap k a -> Maybe a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup k
key HashMap k a
lib)

selectBy :: (Failure e m, Selectable k a c, Monad m) => e -> k -> c -> m a
selectBy :: e -> k -> c -> m a
selectBy e
err = m a -> (a -> m a) -> k -> c -> m a
forall k a c d. Selectable k a c => d -> (a -> d) -> k -> c -> d
selectOr (e -> m a
forall error (f :: * -> *) v. Failure error f => error -> f v
failure e
err) a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure