# Sequence of lifting transformation operators Classic List Threaded 5 messages Open this post in threaded view
|

## Sequence of lifting transformation operators

 A couple of times I find myself wishing for an easy way to transform a function by picking and choosing which of its operators are lifted. For example, consider f <\$> x1 <*> pure x2 <*> x3 <*> pure x4 we can put all the details of this into f itself f' x1 x2 x3 x4 = f <\$> x1 <*> pure x2 <*> x3 <*> pure x4 and then just write f' x1 x2 x3 x4 I think it might be nice to have a series of transformation functions that made this easy to write.  Something like a series of operator like so f' = f <\$_\$_> where it would be read that f' is a lifted f such that the first argument is lifted, the second is not, the third is, and the fourth is not (this is consistent with f <\$> returning a being a lifted f with first argument being lifted). This would make code such as the following flip (go finalX finalY) y `liftM` mx = go <__\$_> finalX finalY mx y https://github.com/snoyberg/conduit/blob/be803218b5b2acaad2eb720ca3a27a4d0734fba8/conduit/Data/Conduit/Internal/Conduit.hs#L543much more robust to write (how it gets written now depends very much on the number of arguments, their order, which ones are lifted, etc.), a whole lot easier to read, and don't even get me started on the points free use (go <__\$_>)! A library could easily provide the first six or so variants (2^6 = 64 functions).  If they were really useful the compiler could provide the rest. <\$> :: (a -> b) -> f a -> f b <\$\$> :: (a -> b -> c) -> f a -> f b -> f c <\$_> :: (a -> b -> c) -> f a -> b -> f c <_\$> :: (a -> b -> c) -> a -> f b -> f c ... Cheers!  -Tyson PS:  It would be nice to also have ones that work with f being lifted. That is like how we have <\$> for an unlifted f and <*> for a lifted f. <*> :: f (a -> b) -> f a -> f b <**> :: f (a -> b -> c) -> f a -> f b -> f c <*_> :: f (a -> b -> c) -> f a -> b -> f c <_*> :: f (a -> b -> c) -> a -> f b -> f c ... A bit of a pain here is that <**> is actually already taken as <*> with reversed arguments.  Possibly this would call for something like this instead <\$^> :: (a -> b) -> f a -> f b <\$^^> :: (a -> b -> c) -> f a -> f b -> f c <\$^_> :: (a -> b -> c) -> f a -> b -> f c <\$_^> :: (a -> b -> c) -> a -> f b -> f c ... and <*^> :: f (a -> b) -> f a -> f b <*^^> :: f (a -> b -> c) -> f a -> f b -> f c <*^_> :: f (a -> b -> c) -> f a -> b -> f c <*_^> :: f (a -> b -> c) -> a -> f b -> f c ... where they are prefixed by \$ or * to indicate what type f is and then _ encodes an unlifted argument position and ^ a lifted argument position. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafeOnly members subscribed via the mailman list are allowed to post.
Open this post in threaded view
|

## Re: Sequence of lifting transformation operators

 Tyson Whitehead wrote: > <\$\$> :: (a -> b -> c) -> f a -> f b -> f c I'd just like to point out that this operator is often used by as the oeprator for fmap2:   (<\$\$>) :: (Functor f1, Functor f) => (a -> b) -> f (f1 a) -> f (f1 b)   (<\$\$>) = fmap . fmap Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafeOnly members subscribed via the mailman list are allowed to post.
Open this post in threaded view
|

## Re: Sequence of lifting transformation operators

 This is (IMO) very similar in use-case to Idris' bang-notation. I'll give a brief summary of what that is and then explain the pros/cons that I see between them. In Idris the do notation has the added notation that do return \$ !a + !b would desugar to do   a' <- a   b' <- b   return \$ a' + b' So !a unwraps a higher up and then uses the unwrapped version. Thus if you want to apply a function to apply a function to some wrapped and some unwrapped values: do return \$ f !a b !c !d Pros/Cons: - Idris notation is (IMO) more visually appealing.   - In particular, it puts the information about which arguments are lifted next     to the arguments themselves, which matches our intuition about what's going on - While it matches our intuition, it does *not* match what's actually going on,   so that's a con. - Idris notation can lift things more than once:   do return \$ f !!a !b !!!!c - Idris notation is syntactic sugar, not a first-class operator   - So that means no currying, no passing it in as an argument, etc. (though     with lambdas this is not as bad as it otherwise would be) - Idris notation is for monads, so it would not work for things that are   applicative but not monads (though I'm not entirely sure what falls into this   category) What do you y'all think? Do they operate in different enough spaces that they should both exist (like applicatives and moands), or is one clearly better?   --Taeer _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafeOnly members subscribed via the mailman list are allowed to post.