-- | A simple NonEmpty dict wrapper to protect us from writing invalid empty Dicts
-- to Redis Hashes.
module NonEmptyDict
  ( NonEmptyDict,
    fromDict,
    toDict,
    toNonEmptyList,
    init,
    keys,
  )
where

import Data.List.NonEmpty (NonEmpty ((:|)))
import Dict

-- | A Dict with at least one entry. For use in writing to redis, where it's an
-- error when writing nothing
data NonEmptyDict k v
  = NonEmptyDict (k, v) (Dict.Dict k v)
  deriving (Int -> NonEmptyDict k v -> ShowS
[NonEmptyDict k v] -> ShowS
NonEmptyDict k v -> String
(Int -> NonEmptyDict k v -> ShowS)
-> (NonEmptyDict k v -> String)
-> ([NonEmptyDict k v] -> ShowS)
-> Show (NonEmptyDict k v)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall k v. (Show k, Show v) => Int -> NonEmptyDict k v -> ShowS
forall k v. (Show k, Show v) => [NonEmptyDict k v] -> ShowS
forall k v. (Show k, Show v) => NonEmptyDict k v -> String
showList :: [NonEmptyDict k v] -> ShowS
$cshowList :: forall k v. (Show k, Show v) => [NonEmptyDict k v] -> ShowS
show :: NonEmptyDict k v -> String
$cshow :: forall k v. (Show k, Show v) => NonEmptyDict k v -> String
showsPrec :: Int -> NonEmptyDict k v -> ShowS
$cshowsPrec :: forall k v. (Show k, Show v) => Int -> NonEmptyDict k v -> ShowS
Show)

-- | tries to create a 'NonEmptyDict' from a 'Dict'
fromDict :: Ord k => Dict.Dict k v -> Maybe (NonEmptyDict k v)
fromDict :: Dict k v -> Maybe (NonEmptyDict k v)
fromDict Dict k v
dict =
  case Dict k v -> List (k, v)
forall k v. Dict k v -> List (k, v)
Dict.toList Dict k v
dict of
    [] -> Maybe (NonEmptyDict k v)
forall a. Maybe a
Nothing
    (k
k, v
v) : List (k, v)
_ -> NonEmptyDict k v -> Maybe (NonEmptyDict k v)
forall a. a -> Maybe a
Just (NonEmptyDict k v -> Maybe (NonEmptyDict k v))
-> NonEmptyDict k v -> Maybe (NonEmptyDict k v)
forall a b. (a -> b) -> a -> b
<| k -> v -> Dict k v -> NonEmptyDict k v
forall k v. Ord k => k -> v -> Dict k v -> NonEmptyDict k v
init k
k v
v Dict k v
dict

-- | creates a 'Dict' from a 'NonEmptyDict'
toDict :: Ord k => NonEmptyDict k v -> Dict k v
toDict :: NonEmptyDict k v -> Dict k v
toDict (NonEmptyDict (k
k, v
v) Dict k v
dict) =
  k -> v -> Dict k v -> Dict k v
forall comparable v.
Ord comparable =>
comparable -> v -> Dict comparable v -> Dict comparable v
Dict.insert k
k v
v Dict k v
dict

-- | creates a 'Dict' from a 'NonEmptyDict'
toNonEmptyList :: NonEmptyDict k v -> NonEmpty (k, v)
toNonEmptyList :: NonEmptyDict k v -> NonEmpty (k, v)
toNonEmptyList (NonEmptyDict (k, v)
kv Dict k v
dict) =
  (k, v)
kv (k, v) -> [(k, v)] -> NonEmpty (k, v)
forall a. a -> [a] -> NonEmpty a
:| Dict k v -> [(k, v)]
forall k v. Dict k v -> List (k, v)
Dict.toList Dict k v
dict

-- | creates a `Dict` from a key, value, and dict
init :: Ord k => k -> v -> Dict.Dict k v -> NonEmptyDict k v
init :: k -> v -> Dict k v -> NonEmptyDict k v
init k
key v
val Dict k v
dict =
  (k, v) -> Dict k v -> NonEmptyDict k v
forall k v. (k, v) -> Dict k v -> NonEmptyDict k v
NonEmptyDict (k
key, v
val) (k -> Dict k v -> Dict k v
forall comparable v.
Ord comparable =>
comparable -> Dict comparable v -> Dict comparable v
Dict.remove k
key Dict k v
dict)