module Music.Score.Internal.Util where
import Control.Lens
import Control.Monad.Plus
import Control.Applicative
import qualified Data.Char
import qualified Data.Monoid
import qualified Data.List
import qualified Data.Ratio
divideList :: Int -> [a] -> [[a]]
divideList n xs
| length xs <= n = [xs]
| otherwise = [take n xs] ++ (divideList n $ drop n xs)
splitWhile :: (a -> Bool) -> [a] -> [[a]]
splitWhile p xs = case splitWhile' p xs of
[]:xss -> xss
xss -> xss
where
splitWhile' p [] = [[]]
splitWhile' p (x:xs) = case splitWhile' p xs of
(xs:xss) -> if p x then []:(x:xs):xss else (x:xs):xss
breakList :: Int -> [a] -> [a] -> [a]
breakList n z = Data.Monoid.mconcat . Data.List.intersperse z . divideList n
mapIndexed :: (Int -> a -> b) -> [a] -> [b]
mapIndexed f as = map (uncurry f) (zip is as)
where
n = length as 1
is = [0..n]
dup :: a -> (a,a)
dup x = (x,x)
unf :: (a -> Maybe a) -> a -> [a]
unf f = Data.List.unfoldr (fmap dup . f)
mapF f = mapFTL f id id
mapT f = mapFTL id f id
mapL f = mapFTL id id f
mapFTL :: (a -> b) -> (a -> b) -> (a -> b) -> [a] -> [b]
mapFTL f g h = go
where
go [] = []
go [a] = [f a]
go [a,b] = [f a, h b]
go xs = [f $ head xs] ++
map g (tail $ init xs) ++
[h $ last xs]
filterOnce :: (a -> Bool) -> [a] -> [a]
filterOnce p = Data.List.takeWhile p . Data.List.dropWhile (not . p)
rots :: [a] -> [[a]]
rots xs = init (zipWith (++) (Data.List.tails xs) (Data.List.inits xs))
rotl :: [a] -> [a]
rotl [] = []
rotl (x:xs) = xs ++ [x]
rotr :: [a] -> [a]
rotr [] = []
rotr xs = last xs : init xs
rotated :: Int -> [a] -> [a]
rotated = go
where
go n as
| n >= 0 = iterate rotr as !! n
| n < 0 = iterate rotl as !! abs n
curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
curry3 = curry . curry . (. tripl)
uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry3 = (. untripl) . uncurry . uncurry
untripl :: (a,b,c) -> ((a,b),c)
untripl (a,b,c) = ((a,b),c)
tripl :: ((a,b),c) -> (a,b,c)
tripl ((a,b),c) = (a,b,c)
tripr :: (a,(b,c)) -> (a,b,c)
tripr (a,(b,c)) = (a,b,c)
partial2 :: (a -> b -> Bool) -> a -> b -> Maybe b
partial3 :: (a -> b -> c -> Bool) -> a -> b -> c -> Maybe c
partial2 f = curry (fmap snd . partial (uncurry f))
partial3 f = curry3 (fmap (view _3) . partial (uncurry3 f))
list :: r -> ([a] -> r) -> [a] -> r
list z f [] = z
list z f xs = f xs
merge :: Ord a => [a] -> [a] -> [a]
merge = mergeBy compare
mergeBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
mergeBy f = mergeBy' $ (fmap.fmap) orderingToBool f
where
orderingToBool LT = True
orderingToBool EQ = True
orderingToBool GT = False
mergeBy' :: (a -> a -> Bool) -> [a] -> [a] -> [a]
mergeBy' pred xs [] = xs
mergeBy' pred [] ys = ys
mergeBy' pred (x:xs) (y:ys) =
case pred x y of
True -> x: mergeBy' pred xs (y:ys)
False -> y: mergeBy' pred (x:xs) ys
composed :: [b -> b] -> b -> b
composed = Prelude.foldr (.) id
unRatio :: Integral a => Data.Ratio.Ratio a -> (a, a)
unRatio x = (Data.Ratio.numerator x, Data.Ratio.denominator x)
showRatio :: (Integral a, Show a) => Data.Ratio.Ratio a -> String
showRatio (realToFrac -> (unRatio -> (x, 1))) = show x
showRatio (realToFrac -> (unRatio -> (x, y))) = "(" ++ show x ++ "/" ++ show y ++ ")"
retainUpdates :: Eq a => [a] -> [Maybe a]
retainUpdates = snd . Data.List.mapAccumL g Nothing where
g Nothing x = (Just x, Just x)
g (Just p) x = (Just x, if p == x then Nothing else Just x)
replic :: Integral a => a -> b -> [b]
replic n = replicate (fromIntegral n)
swap :: (a, b) -> (b, a)
swap (x, y) = (y, x)
withNext :: [a] -> [(a, Maybe a)]
withNext = fmap (\(p,c,n) -> (c,n)) . withPrevNext
withPrev :: [a] -> [(Maybe a, a)]
withPrev = fmap (\(p,c,n) -> (p,c)) . withPrevNext
withPrevNext :: [a] -> [(Maybe a, a, Maybe a)]
withPrevNext xs = zip3 (pure Nothing ++ fmap Just xs) xs (fmap Just (tail xs) ++ repeat Nothing)
mapWithNext :: (a -> Maybe a -> b) -> [a] -> [b]
mapWithNext f = map (uncurry f) . withNext
mapWithPrev :: (Maybe a -> a -> b) -> [a] -> [b]
mapWithPrev f = map (uncurry f) . withPrev
mapWithPrevNext :: (Maybe a -> a -> Maybe a -> b) -> [a] -> [b]
mapWithPrevNext f = map (uncurry3 f) . withPrevNext
toDouble :: Real a => a -> Double
toDouble = realToFrac
through :: Applicative f =>
Lens' s a
-> Lens s t a b
-> Lens (f s) (f t) (f a) (f b)
through lens1 lens2 = lens getter (flip setter)
where
getter = fmap (view lens1)
setter = liftA2 (over lens2 . const)
single :: Prism' [a] a
single = prism' return $ \xs -> case xs of
[x] -> Just x
_ -> Nothing
floor' :: RealFrac a => a -> a
floor' = fromIntegral . floor
inspecting :: Eq a => (b -> a) -> b -> b -> Bool
inspecting p x y = p x == p y