module Polysemy.Plugin.Fundep.Utils  where

import Control.Applicative
import Data.Bifunctor
import Data.List



------------------------------------------------------------------------------
-- | Returns the head of the list iff there is exactly one element.
singleListToJust :: [a] -> Maybe a
singleListToJust :: [a] -> Maybe a
singleListToJust [a
a] = a -> Maybe a
forall a. a -> Maybe a
Just a
a
singleListToJust [a]
_ = Maybe a
forall a. Maybe a
Nothing


------------------------------------------------------------------------------
-- | Like 'Control.Monad.when', but in the context of an 'Alternative'.
whenA
    :: (Monad m, Alternative z)
    => Bool
    -> m a
    -> m (z a)
whenA :: Bool -> m a -> m (z a)
whenA Bool
False m a
_ = z a -> m (z a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure z a
forall (f :: * -> *) a. Alternative f => f a
empty
whenA Bool
True m a
ma = a -> z a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> z a) -> m a -> m (z a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
ma


------------------------------------------------------------------------------
-- | Count the number of times 'a' is present in the list.
countLength ::  Eq a => [a] -> [(a, Int)]
countLength :: [a] -> [(a, Int)]
countLength [a]
as =
  let grouped :: [[a]]
grouped = [a] -> [[a]]
forall a. Eq a => [a] -> [[a]]
group [a]
as
   in ([a] -> [a] -> (a, Int)) -> [[a]] -> [[a]] -> [(a, Int)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ((([a], [a]) -> (a, Int)) -> [a] -> [a] -> (a, Int)
forall a b c. ((a, b) -> c) -> a -> b -> c
curry ((([a], [a]) -> (a, Int)) -> [a] -> [a] -> (a, Int))
-> (([a], [a]) -> (a, Int)) -> [a] -> [a] -> (a, Int)
forall a b. (a -> b) -> a -> b
$ ([a] -> a) -> ([a] -> Int) -> ([a], [a]) -> (a, Int)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap [a] -> a
forall a. [a] -> a
head [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length) [[a]]
grouped [[a]]
grouped