Applicative ((->) c) methods

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Applicative ((->) c) methods

Keith
Just thinking for Applicative ((->) c)
(<*) = const
(*>) = flip const -- or \ _ x -> x

Is it because we can rely on GHC to produce the same code from the current definitions?


Also wondering why Monad uses
f >>= k = \ r -> k (f r) r

but Applicative uses
(<*>) f g x = f x (g x)
liftA2 q f g x = q (f x) (g x)

Seems like if it's style/legibility, it should be consistent between (>>=) and (<*>). And if it's inlining issue, we'd want lambdas for all three.

--Keith
--
Sent from my phone with K-9 Mail.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Applicative ((->) c) methods

Carter Schonwald
hey Keith,
when emailing to the library list, linking to the source code you're referring to: http://hackage.haskell.org/package/base-4.11.0.0/docs/src/GHC.Base.html#line-804 
can be super helpful for making sure everyone is on the same page ! (i think i'm linking to the right code, plz confirm!)

unless the commit history indicates otherwise, i'd presume any current choices in base are largely a product of historical reasons and or the style of whomever wrote it most recently? 

you are absolutely correct that when it comes to inlining,  "foo = \x ->  .. " will always satisfy the saturation condition to get inlined, while "foo x = ..." will only be marked saturated when fully applied, (and this of course ignoring how specializing the type class instances of a piece of code behaves!)

i do generally agree that the RHS style you allude to is very handy when i "know" that the definition should essentially simplify/partial evaluate away to some function application and or let expression (especially if the resulting code looks non recursive! ) to help ghc along, though excessive inlining can be quite bad too! (Austin Seipp and Edward K have some really good long comments on reddit etc about this, though i cant find the particular one i'm thinking of by austin from a few years back).  

one point Austin made was along the lines of: if you have to tell ghc when/how to inline something to get good performance, this should be treated as a bug (by and large). 

though of course for core libraries interfaces/definitions/performance critical primops, that guidance isn't necessarily the right default

I think the best approach to grounding these sorts of performance motivated changes is to 

1) write a tiny application / benchmark demonstrator with your own locally defined / newtypy versions of both definitions you wanna compare
2) if need be, compare two versions of the same commit of ghc etc, (with one having the proposed change set in base), and running nofib et al  to have a statistical characterization of impact! 

That said, i definitely agree with the implication that point free style (aka partially applied ) code using the (-> r) applicative/monad definitions, such as might be found in the lens library "over" and friends, may or may not benefit from this sort of change. Though i suspect Eric Mertens or Edward K or Ryan Scott might have better clarity on that


Thanks for taking the time to think about this and ask/start a discussion! '

-Carter

On Mon, Nov 18, 2019 at 3:40 PM Keith <[hidden email]> wrote:
Just thinking for Applicative ((->) c)
(<*) = const
(*>) = flip const -- or \ _ x -> x

Is it because we can rely on GHC to produce the same code from the current definitions?


Also wondering why Monad uses
f >>= k = \ r -> k (f r) r

but Applicative uses
(<*>) f g x = f x (g x)
liftA2 q f g x = q (f x) (g x)

Seems like if it's style/legibility, it should be consistent between (>>=) and (<*>). And if it's inlining issue, we'd want lambdas for all three.

--Keith
--
Sent from my phone with K-9 Mail._______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Applicative ((->) c) methods

Tony Morris-4
In reply to this post by Keith
This is incorrect.

(<*) = liftA2 const
(*>) = liftA2 (flip const)

On 19/11/19 6:40 am, Keith wrote:
> Just thinking for Applicative ((->) c)
> (<*) = const
> (*>) = flip const -- or \ _ x -> x
>


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

signature.asc (499 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Applicative ((->) c) methods

David Feuer
Both are correct. 

On Wed, Nov 20, 2019, 12:15 AM Tony Morris <[hidden email]> wrote:
This is incorrect.

(<*) = liftA2 const
(*>) = liftA2 (flip const)

On 19/11/19 6:40 am, Keith wrote:
> Just thinking for Applicative ((->) c)
> (<*) = const
> (*>) = flip const -- or \ _ x -> x
>

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Applicative ((->) c) methods

Tony Morris-4

No, they are not the same function.

λ> let (*>) = flip const in putStrLn "hi" *> putStrLn "bye"
bye
λ> let (*>) = liftA2 (flip const) in putStrLn "hi" *> putStrLn "bye"
hi
bye

On 20/11/19 3:41 pm, David Feuer wrote:
Both are correct. 

On Wed, Nov 20, 2019, 12:15 AM Tony Morris <[hidden email]> wrote:
This is incorrect.

(<*) = liftA2 const
(*>) = liftA2 (flip const)

On 19/11/19 6:40 am, Keith wrote:
> Just thinking for Applicative ((->) c)
> (<*) = const
> (*>) = flip const -- or \ _ x -> x
>

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

signature.asc (499 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Applicative ((->) c) methods

David Feuer
They're not the same in general, no, but they're the same for the ((->) c) Applicative, which is the topic of this discussion.

On Wed, Nov 20, 2019, 1:04 AM Tony Morris <[hidden email]> wrote:

No, they are not the same function.

λ> let (*>) = flip const in putStrLn "hi" *> putStrLn "bye"
bye
λ> let (*>) = liftA2 (flip const) in putStrLn "hi" *> putStrLn "bye"
hi
bye

On 20/11/19 3:41 pm, David Feuer wrote:
Both are correct. 

On Wed, Nov 20, 2019, 12:15 AM Tony Morris <[hidden email]> wrote:
This is incorrect.

(<*) = liftA2 const
(*>) = liftA2 (flip const)

On 19/11/19 6:40 am, Keith wrote:
> Just thinking for Applicative ((->) c)
> (<*) = const
> (*>) = flip const -- or \ _ x -> x
>

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Applicative ((->) c) methods

Carter Schonwald
Indeed. For the fucntions as reader applicative david is correct. 

On Wed, Nov 20, 2019 at 1:07 AM David Feuer <[hidden email]> wrote:
They're not the same in general, no, but they're the same for the ((->) c) Applicative, which is the topic of this discussion.

On Wed, Nov 20, 2019, 1:04 AM Tony Morris <[hidden email]> wrote:

No, they are not the same function.

λ> let (*>) = flip const in putStrLn "hi" *> putStrLn "bye"
bye
λ> let (*>) = liftA2 (flip const) in putStrLn "hi" *> putStrLn "bye"
hi
bye

On 20/11/19 3:41 pm, David Feuer wrote:
Both are correct. 

On Wed, Nov 20, 2019, 12:15 AM Tony Morris <[hidden email]> wrote:
This is incorrect.

(<*) = liftA2 const
(*>) = liftA2 (flip const)

On 19/11/19 6:40 am, Keith wrote:
> Just thinking for Applicative ((->) c)
> (<*) = const
> (*>) = flip const -- or \ _ x -> x
>

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries