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/be803218b5b2acaad2eb720ca3a27a4d073... much 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.

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/

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

What is the order of unwrapping?
`return $ !a + !b` doesn't equals `return $ !b + !a` right?
2017-01-31 9:37 GMT+05:00 Taeer Bar-Yam
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-cafe Only members subscribed via the mailman list are allowed to post.

In general no. IMO this is better used with commutative monads (is that the right term?) such as [] or Maybe, rather than monads such as IO. However, there is a well-defined order, that I presume is inner-to-outer left-to-right, but I don't actually have experience programming in Idris. Reference: http://docs.idris-lang.org/en/latest/tutorial/interfaces.html#notation Excerpts from Alexey Vagarenko's message of January 31, 2017 12:56 am:
What is the order of unwrapping? `return $ !a + !b` doesn't equals `return $ !b + !a` right?
--Taeer
participants (4)
-
Alexey Vagarenko
-
Erik de Castro Lopo
-
Taeer Bar-Yam
-
Tyson Whitehead