module Tip.Utils where
import Data.List
import Data.Maybe
import Data.Graph hiding (components)
import Data.List.Split
import Data.Char
import Data.Foldable (Foldable)
import qualified Data.Foldable as F
import Data.Function (on)
import Data.Ord
import Data.Function
usort :: Ord a => [a] -> [a]
usort = usortOn id
usortOn :: Ord b => (a -> b) -> [a] -> [a]
usortOn f = map head . groupBy ((==) `on` f) . sortBy (comparing f)
unionOn :: Ord b => (a -> b) -> [a] -> [a] -> [a]
unionOn k = unionBy ((==) `on` k)
duplicates :: Ord a => [a] -> [a]
duplicates xs = usort [ x | x <- xs, count x > 1 ]
where count x = length (filter (== x) xs)
data Component a = Rec [a] | NonRec a
deriving (Eq,Ord,Show,Functor)
flattenComponent :: Component a -> [a]
flattenComponent (Rec xs) = xs
flattenComponent (NonRec x) = [x]
components :: Ord name => (thing -> name) -> (thing -> [name]) -> [thing] -> [Component thing]
components name refers things =
[ case comp of
[(thing,n,refs)]
| n `notElem` refs -> NonRec thing
_ -> Rec [ thing | (thing,_,_) <- comp ]
| comp <- map flattenSCC $ stronglyConnCompR
[ (thing,name thing,filter (`elem` names) (refers thing))
| thing <- things
]
]
where
names = map name things
lookupComponent :: Eq thing => thing -> [Component thing] -> Maybe (Component thing)
lookupComponent x = listToMaybe . mapMaybe h
where
h c = case c of NonRec y | x == y -> Just c
Rec ys | x `elem` ys -> Just c
_ -> Nothing
sortThings :: Ord name => (thing -> name) -> (thing -> [name]) -> [thing] -> [[thing]]
sortThings name refers things = map flattenComponent (components name refers things)
recursive :: Ord name => (thing -> name) -> (thing -> [name]) -> [thing] -> [name]
recursive name refers things =
[ name x | Rec xs <- components name refers things, x <- xs ]
flagify :: String -> String
flagify
= map toLower . intercalate "-"
. split (condense $ dropInitBlank $ keepDelimsL $ whenElt (\x -> isUpper x || isSpace x))
flagifyShow :: Show a => a -> String
flagifyShow = flagify . show
maximumOn :: forall f a b . (F.Foldable f,Ord b) => (a -> b) -> f a -> b
maximumOn f = f . F.maximumBy (comparing f)
withPrevious :: [a] -> [(a,[a])]
withPrevious xs = zip xs (inits xs)
cursor :: [a] -> [([a],a,[a])]
cursor xs = [ let (l,x:r) = splitAt i xs in (l,x,r) | i <- [0..length xs1] ]