-- | Extensions to "Data.Maybe". module Music.Theory.Maybe where import Data.Maybe {- base -} -- | Variant with error text. from_just :: String -> Maybe a -> a from_just err = fromMaybe (error err) -- | Variant of unzip. -- -- > let r = ([Just 1,Nothing,Just 3],[Just 'a',Nothing,Just 'c']) -- > in maybe_unzip [Just (1,'a'),Nothing,Just (3,'c')] == r maybe_unzip :: [Maybe (a,b)] -> ([Maybe a],[Maybe b]) maybe_unzip = let f x = case x of Nothing -> (Nothing,Nothing) Just (i,j) -> (Just i,Just j) in unzip . map f -- | Replace 'Nothing' elements with last 'Just' value. This does not -- alter the length of the list. -- -- > maybe_latch 1 [Nothing,Just 2,Nothing,Just 4] == [1,2,2,4] maybe_latch :: a -> [Maybe a] -> [a] maybe_latch i x = case x of [] -> [] Just e:x' -> e : maybe_latch e x' Nothing:x' -> i : maybe_latch i x' -- | Variant requiring initial value is not 'Nothing'. -- -- > maybe_latch1 [Just 1,Nothing,Nothing,Just 4] == [1,1,1,4] maybe_latch1 :: [Maybe a] -> [a] maybe_latch1 = maybe_latch (error "maybe_latch1") -- | 'map' of 'fmap'. -- -- > maybe_map negate [Nothing,Just 2] == [Nothing,Just (-2)] maybe_map :: (a -> b) -> [Maybe a] -> [Maybe b] maybe_map = map . fmap -- | If either is 'Nothing' then 'False', else /eq/ of values. maybe_eq_by :: (t -> u -> Bool) -> Maybe t -> Maybe u -> Bool maybe_eq_by eq_fn p q = case (p,q) of (Just p',Just q') -> eq_fn p' q' _ -> False -- | Join two values, either of which may be missing. maybe_join' :: (s -> t) -> (s -> s -> t) -> Maybe s -> Maybe s -> Maybe t maybe_join' f g p q = case (p,q) of (Nothing,_) -> fmap f q (_,Nothing) -> fmap f p (Just p',Just q') -> Just (p' `g` q') -- | 'maybe_join'' of 'id' maybe_join :: (t -> t -> t) -> Maybe t -> Maybe t -> Maybe t maybe_join = maybe_join' id -- | Apply predicate inside 'Maybe'. -- -- > maybe_predicate even (Just 3) == Nothing maybe_predicate :: (a -> Bool) -> Maybe a -> Maybe a maybe_predicate f i = case i of Nothing -> Nothing Just j -> if f j then Just j else Nothing -- | 'map' of 'maybe_predicate'. -- -- > let r = [Nothing,Nothing,Nothing,Just 4] -- > in maybe_filter even [Just 1,Nothing,Nothing,Just 4] == r maybe_filter :: (a -> Bool) -> [Maybe a] -> [Maybe a] maybe_filter = map . maybe_predicate -- | Variant of 'Data.List.filter' that retains 'Nothing' as a -- placeholder for removed elements. -- -- > filter_maybe even [1..4] == [Nothing,Just 2,Nothing,Just 4] filter_maybe :: (a -> Bool) -> [a] -> [Maybe a] filter_maybe f = maybe_filter f . map Just