{-# LANGUAGE BangPatterns #-}
module Slist.Maybe
( maybeToSlist
, slistToMaybe
, catMaybes
, mapMaybe
, slistWith
) where
import Data.Bifunctor (second)
import Slist.Size (Size (..))
import Slist.Type (Slist (..), cons, one)
import qualified Data.Maybe as M
maybeToSlist :: Maybe a -> Slist a
maybeToSlist :: Maybe a -> Slist a
maybeToSlist = Slist a -> (a -> Slist a) -> Maybe a -> Slist a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Slist a
forall a. Monoid a => a
mempty a -> Slist a
forall a. a -> Slist a
one
{-# INLINE maybeToSlist #-}
slistToMaybe :: Slist a -> Maybe a
slistToMaybe :: Slist a -> Maybe a
slistToMaybe = (a -> Maybe a -> Maybe a) -> Maybe a -> Slist a -> Maybe a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Maybe a -> Maybe a -> Maybe a
forall a b. a -> b -> a
const (Maybe a -> Maybe a -> Maybe a)
-> (a -> Maybe a) -> a -> Maybe a -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall a. a -> Maybe a
Just) Maybe a
forall a. Maybe a
Nothing
{-# INLINE slistToMaybe #-}
catMaybes :: Slist (Maybe a) -> Slist a
catMaybes :: Slist (Maybe a) -> Slist a
catMaybes = (Maybe a -> Maybe a) -> Slist (Maybe a) -> Slist a
forall b a. (a -> Maybe b) -> Slist a -> Slist b
mapMaybe Maybe a -> Maybe a
forall a. a -> a
id
{-# INLINE catMaybes #-}
mapMaybe :: forall b a . (a -> Maybe b) -> Slist a -> Slist b
mapMaybe :: (a -> Maybe b) -> Slist a -> Slist b
mapMaybe a -> Maybe b
_ (Slist [] Size
_) = Slist b
forall a. Monoid a => a
mempty
mapMaybe a -> Maybe b
f (Slist [a]
xs Size
Infinity) = [b] -> Size -> Slist b
forall a. [a] -> Size -> Slist a
Slist ((a -> Maybe b) -> [a] -> [b]
forall a b. (a -> Maybe b) -> [a] -> [b]
M.mapMaybe a -> Maybe b
f [a]
xs) Size
Infinity
mapMaybe a -> Maybe b
f (Slist (a
x:[a]
xs) Size
n) = case a -> Maybe b
f a
x of
Maybe b
Nothing -> Slist b
rest
Just b
r -> b -> Slist b -> Slist b
forall a. a -> Slist a -> Slist a
cons b
r Slist b
rest
where
rest :: Slist b
rest :: Slist b
rest = (a -> Maybe b) -> Slist a -> Slist b
forall b a. (a -> Maybe b) -> Slist a -> Slist b
mapMaybe a -> Maybe b
f ([a] -> Size -> Slist a
forall a. [a] -> Size -> Slist a
Slist [a]
xs (Size
n Size -> Size -> Size
forall a. Num a => a -> a -> a
- Size
1))
{-# NOINLINE [1] mapMaybe #-}
slistWith :: forall b a . (a -> Maybe b) -> [a] -> Slist b
slistWith :: (a -> Maybe b) -> [a] -> Slist b
slistWith a -> Maybe b
f [a]
l = let (Int
n, [b]
sl) = Int -> [a] -> (Int, [b])
go Int
0 [a]
l in [b] -> Size -> Slist b
forall a. [a] -> Size -> Slist a
Slist [b]
sl (Int -> Size
Size Int
n)
where
go :: Int -> [a] -> (Int, [b])
go :: Int -> [a] -> (Int, [b])
go !Int
accSize [] = (Int
accSize, [])
go !Int
accSize (a
x:[a]
xs) = case a -> Maybe b
f a
x of
Maybe b
Nothing -> Int -> [a] -> (Int, [b])
go Int
accSize [a]
xs
Just b
r -> ([b] -> [b]) -> (Int, [b]) -> (Int, [b])
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (b
rb -> [b] -> [b]
forall a. a -> [a] -> [a]
:) ((Int, [b]) -> (Int, [b])) -> (Int, [b]) -> (Int, [b])
forall a b. (a -> b) -> a -> b
$ Int -> [a] -> (Int, [b])
go (Int
accSize Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [a]
xs