New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lack of functions which query with passthrough in monad #719

Open
uzytkownik opened this Issue Mar 24, 2017 · 5 comments

Comments

Projects
None yet
4 participants
@uzytkownik

uzytkownik commented Mar 24, 2017

There are functions which allow to run return different value then set and functions which allow to run monadic actions but there aren't functions which do both. Below are samples of such functions

newtype MonoidInApp m r = MonoidInApp {getMonoidInApp :: m r}

instance (Semigroup r, Apply m) => Semigroup (MonoidInApp m r) where
    MonoidInApp l <> MonoidInApp r = MonoidInApp ((<>) <$> l <.> r)

instance (Monoid r, Applicative m) => Monoid (MonoidInApp m r) where
    mempty = MonoidInApp $ pure mempty
    mappend (MonoidInApp l) (MonoidInApp r) = MonoidInApp (mappend <$> l <*> r)

useMap :: MonadState s m => Getting (MonoidInApp m a) s b -> (b -> m a) -> m a
useMap l f = join . fmap getMonoidInApp . use $ l . to f . iso MonoidInApp getMonoidInApp

viewMap :: MonadReader s m => Getting (MonoidInApp m a) s b -> (b -> m a) -> m a
viewMap l f = join . fmap getMonoidInApp . view $ l . to f . iso MonoidInApp getMonoidInApp

newtype TupleT f a b = TupleT {getTuple :: f (a, b)}

instance Functor f => Functor (TupleT f a) where
    fmap f = TupleT . fmap (fmap f) . getTuple

instance (Apply f, Semigroup m) => Apply (TupleT f m) where
    TupleT l <.> TupleT r = TupleT ((\(la, lb) (ra, rb) -> (la <> ra, lb rb)) <$> l <.> r)

instance (Applicative f, Monoid m) => Applicative (TupleT f m) where
    pure = TupleT . pure . (,) mempty
    TupleT l <*> TupleT r = TupleT ((\(la, lb) (ra, rb) -> (la `mappend` ra, lb rb)) <$> l <*> r)

gather :: LensLike (TupleT f r) s t a b -> (a -> f (r, b)) -> s -> f (r, t)
gather l f = getTuple . (l $ TupleT . f)

gatherState :: MonadState s m => LensLike (TupleT m r) s s a b -> (a -> m (r, b)) -> m r
gatherState l f = get >>= gather l f >>= \(r, s) -> (r <$ put s)
@phadej

This comment has been minimized.

Show comment
Hide comment
@phadej

phadej Mar 24, 2017

Collaborator

I.e. you want the generalisation of <%~, but to be traverseOf + view, instead of over + view?

Seems reasonable to me, I'm not sure whether the gather is a good name though.

Collaborator

phadej commented Mar 24, 2017

I.e. you want the generalisation of <%~, but to be traverseOf + view, instead of over + view?

Seems reasonable to me, I'm not sure whether the gather is a good name though.

@phadej

This comment has been minimized.

Show comment
Hide comment
@phadej

phadej Mar 24, 2017

Collaborator

I guess it should be named <%%~, because there is %%~. It's a bit of a monster, but at least consistent.

Collaborator

phadej commented Mar 24, 2017

I guess it should be named <%%~, because there is %%~. It's a bit of a monster, but at least consistent.

@uzytkownik

This comment has been minimized.

Show comment
Hide comment
@uzytkownik

uzytkownik Mar 24, 2017

@phadej Please treat any names as just me being bad at naming. I was more thinking in terms of %%@~/%%@=. then <<%~.

uzytkownik commented Mar 24, 2017

@phadej Please treat any names as just me being bad at naming. I was more thinking in terms of %%@~/%%@=. then <<%~.

@ekmett

This comment has been minimized.

Show comment
Hide comment
@ekmett

ekmett Apr 9, 2017

Owner

I'm not in a huge hurry to add more opaque operators.

I don't have a particularly strong objection to adding combinators along these lines, but the names used don't fit lens very well.

Owner

ekmett commented Apr 9, 2017

I'm not in a huge hurry to add more opaque operators.

I don't have a particularly strong objection to adding combinators along these lines, but the names used don't fit lens very well.

@duog

This comment has been minimized.

Show comment
Hide comment
@duog

duog Apr 10, 2017

Contributor

@phadej asked me to add these to the pr for #722.

Notwithstanding @ekmett's ambivalence, the following two operators seem reasonable to me:

-- this is gather from the OP
(<%%~) :: Functor f => LensLike (Compose f ((,)b)) s t a b -> (a -> f b) -> s -> f (b, t)
l <%%~ f = getCompose . (l $ Compose . fmap (\b -> (b, b)) . f)

(<<%%~) :: Functor f => LensLike (Compose f ((,)a)) s t a b -> (a -> f b) -> s -> f (a, t)
l <<%%~ f = getCompose . (l $ \a -> Compose $ (a,) <$> f a)

however the other operations don't seem to fit very well. %%= already exists and does something a bit different, so adding <%%= and <<%%= as analogues to the codeblock above seems incoherent. useMap and viewMap seem fine except for the names.

I will shelve these for now. I would be happy to add them to #725 if you would like, let me know which ones and what you would like them called.

Contributor

duog commented Apr 10, 2017

@phadej asked me to add these to the pr for #722.

Notwithstanding @ekmett's ambivalence, the following two operators seem reasonable to me:

-- this is gather from the OP
(<%%~) :: Functor f => LensLike (Compose f ((,)b)) s t a b -> (a -> f b) -> s -> f (b, t)
l <%%~ f = getCompose . (l $ Compose . fmap (\b -> (b, b)) . f)

(<<%%~) :: Functor f => LensLike (Compose f ((,)a)) s t a b -> (a -> f b) -> s -> f (a, t)
l <<%%~ f = getCompose . (l $ \a -> Compose $ (a,) <$> f a)

however the other operations don't seem to fit very well. %%= already exists and does something a bit different, so adding <%%= and <<%%= as analogues to the codeblock above seems incoherent. useMap and viewMap seem fine except for the names.

I will shelve these for now. I would be happy to add them to #725 if you would like, let me know which ones and what you would like them called.

@ekmett ekmett added the enhancement label Apr 25, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment