{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Profunctor.Optic.Fold0 (
Fold0
, fold0
, ifold0
, failing
, toFold0
, fromFold0
, folded0
, filtered
, withFold0
, withIxfold0
, (^?)
, preview
, preuse
, ipreview
, ipreviews
, tries
, tries_
, catches
, catches_
, handles
, handles_
, Forget0(..)
, AFold0
, AIxfold0
, Pre(..)
) where
import Control.Exception (Exception)
import Control.Monad.IO.Unlift
import Control.Monad.Reader as Reader hiding (lift)
import Control.Monad.State as State hiding (lift)
import Data.Maybe
import Data.Monoid hiding (All(..), Any(..))
import Data.Profunctor.Optic.Import
import Data.Profunctor.Optic.Prism (just, async)
import Data.Profunctor.Optic.Traversal0 (traversal0Vl, itraversal0Vl, is)
import Data.Profunctor.Optic.Types
import Data.Profunctor.Optic.View
import qualified Control.Exception as Ex
type AFold0 r s a = Optic' (Forget0 r) s a
type AIxfold0 r i s a = IndexedOptic' (Forget0 r) i s a
fold0 :: (s -> Maybe a) -> Fold0 s a
fold0 f = to (\s -> maybe (Left s) Right (f s)) . right'
{-# INLINE fold0 #-}
ifold0 :: (s -> Maybe (i, a)) -> Ixfold0 i s a
ifold0 g = itraversal0Vl (\point f s -> maybe (point s) (uncurry f) $ g s) . coercer
{-# INLINE ifold0 #-}
infixl 3 `failing`
failing :: AFold0 a s a -> AFold0 a s a -> Fold0 s a
failing a b = fold0 $ \s -> maybe (preview b s) Just (preview a s)
{-# INLINE failing #-}
toFold0 :: View s (Maybe a) -> Fold0 s a
toFold0 = (. just)
{-# INLINE toFold0 #-}
fromFold0 :: AFold0 a s a -> View s (Maybe a)
fromFold0 = to . preview
{-# INLINE fromFold0 #-}
folded0 :: Fold0 (Maybe a) a
folded0 = fold0 id
{-# INLINE folded0 #-}
filtered :: (a -> Bool) -> Fold0 a a
filtered p = traversal0Vl (\point f a -> if p a then f a else point a) . coercer
{-# INLINE filtered #-}
withFold0 :: Optic (Forget0 r) s t a b -> (a -> Maybe r) -> s -> Maybe r
withFold0 o = runForget0 #. o .# Forget0
{-# INLINE withFold0 #-}
withIxfold0 :: Monoid i => AIxfold0 r i s a -> (i -> a -> Maybe r) -> s -> Maybe r
withIxfold0 o f = flip curry mempty $ withFold0 o (uncurry f)
{-# INLINE withIxfold0 #-}
infixl 8 ^?
(^?) :: s -> AFold0 a s a -> Maybe a
(^?) = flip preview
{-# INLINE (^?) #-}
preview :: MonadReader s m => AFold0 a s a -> m (Maybe a)
preview o = Reader.asks $ withFold0 o Just
{-# INLINE preview #-}
preuse :: MonadState s m => AFold0 a s a -> m (Maybe a)
preuse o = State.gets $ preview o
{-# INLINE preuse #-}
ipreview :: Monoid i => AIxfold0 (i , a) i s a -> s -> Maybe (i , a)
ipreview o = ipreviews o (,)
{-# INLINE ipreview #-}
ipreviews :: Monoid i => AIxfold0 r i s a -> (i -> a -> r) -> s -> Maybe r
ipreviews o f = withIxfold0 o (\i -> Just . f i)
{-# INLINE ipreviews #-}
tries :: MonadUnliftIO m => Exception ex => AFold0 e ex e -> m a -> m (Either e a)
tries o a = withRunInIO $ \run -> run (Right `liftM` a) `Ex.catch` \e ->
if is async e then throwM e else run $ maybe (throwM e) (return . Left) (preview o e)
{-# INLINE tries #-}
tries_ :: MonadUnliftIO m => Exception ex => AFold0 e ex e -> m a -> m (Maybe a)
tries_ o a = preview right' `liftM` tries o a
{-# INLINE tries_ #-}
catches :: MonadUnliftIO m => Exception ex => AFold0 e ex e -> m a -> (e -> m a) -> m a
catches o a ea = withRunInIO $ \run -> run a `Ex.catch` \e ->
if is async e then throwM e else run $ maybe (throwM e) ea (preview o e)
{-# INLINE catches #-}
catches_ :: MonadUnliftIO m => Exception ex => AFold0 e ex e -> m a -> m a -> m a
catches_ o x y = catches o x $ const y
{-# INLINE catches_ #-}
handles :: MonadUnliftIO m => Exception ex => AFold0 e ex e -> (e -> m a) -> m a -> m a
handles o = flip $ catches o
{-# INLINE handles #-}
handles_ :: MonadUnliftIO m => Exception ex => AFold0 e ex e -> m a -> m a -> m a
handles_ o = flip $ catches_ o
{-# INLINE handles_ #-}
throwM :: MonadIO m => Exception e => e -> m a
throwM = liftIO . Ex.throwIO
{-# INLINE throwM #-}
newtype Forget0 r a b = Forget0 { runForget0 :: a -> Maybe r }
instance Functor (Forget0 r a) where
fmap _ (Forget0 p) = Forget0 p
instance Contravariant (Forget0 r a) where
contramap _ (Forget0 p) = Forget0 p
instance Profunctor (Forget0 r) where
dimap f _ (Forget0 p) = Forget0 (p . f)
instance Choice (Forget0 r) where
left' (Forget0 p) = Forget0 (either p (const Nothing))
right' (Forget0 p) = Forget0 (either (const Nothing) p)
instance Cochoice (Forget0 r) where
unleft (Forget0 k) = Forget0 (k . Left)
unright (Forget0 k) = Forget0 (k . Right)
instance Strong (Forget0 r) where
first' (Forget0 p) = Forget0 (p . fst)
second' (Forget0 p) = Forget0 (p . snd)
instance Sieve (Forget0 r) (Pre r) where
sieve = (Pre .) . runForget0
instance Representable (Forget0 r) where
type Rep (Forget0 r) = Pre r
tabulate = Forget0 . (getPre .)
{-# INLINE tabulate #-}
newtype Pre a b = Pre { getPre :: Maybe a } deriving (Eq, Ord, Show)
instance Functor (Pre a) where fmap _ (Pre p) = Pre p
instance Contravariant (Pre a) where contramap _ (Pre p) = Pre p