packages feed

proton-0.0.1: src/Proton/Wither.hs

{-# LANGUAGE ScopedTypeVariables #-}
module Proton.Wither where

import Data.Profunctor
import Data.Profunctor.Withering
import Control.Applicative
import Proton.Types
import Proton.Prisms

type Wither s t a b = forall p. Withering p => Optic p s t a b
type Wither' s a = Wither s s a a

-- type Selector' s a = Selector s s a a
-- type Selector s t a b = forall p. (Withering p, Depending p) => Optic p s t a b


guarding :: Alternative f => (a -> Bool) -> a -> f a
guarding p a
    | p a = pure a
    | otherwise = empty

guarded :: forall a b. (a -> Bool) -> Wither a b a b
guarded p = cull guarded'
  where
    guarded' :: forall f. Alternative f => (a -> f b) -> a -> f b
    guarded' f a
      | p a = f a
      | otherwise = empty

-- selectResult :: forall a b. (b -> Bool) -> Selector a b a b
-- selectResult p = cull _collapse . depend check
--   where
--     -- collapse :: forall f. Alternative f => (a -> f (b)) -> a -> f b
--     check :: forall f. Monad f => (a -> f b) -> a -> f (Maybe b)
--     check f a = do
--         f a >>= \b ->
--             if p b then pure $ Just b
--                    else pure $ Nothing

filterOf :: Optic (Star Maybe) s t a a -> (a -> Bool) -> s -> Maybe t
filterOf w p s = runStar (w (Star (guarding p))) s

witherPrism :: forall p s t a b. Withering p => Prism s t a b -> Optic p s t a b
witherPrism prsm =
    withPrism prsm $ \embed match ->
      let
        go :: Alternative f => (a -> f b) -> s -> f t
        go f s = 
            case match s of
                Left _ -> empty
                Right a -> fmap embed $ f a
      in cull go