Why is the $! operator right-associative?
Asked Answered
S

2

5

I'm just learning Haskell and I'm still not entirely clear on when and how strict evaluation is forced

When I want a function to evaluate its arguments strictly I find myself writing

((f $! x) $! y ) $! z

which seems weird. Shouldn't $! be left-associative so I could write

f $! x $! y $! z

and have it do what I want?

Am I completely misunderstanding the $! operator?

Swill answered 9/5, 2014 at 17:18 Comment(3)
Why not just write a function !$ with the reversed fixity of $! that does what you want?Evanish
The question is why the function isn't already defined that way. I want to know if my desire to write it that way reflects a misunderstanding of how things in Haskell work.Swill
If you're just learning Haskell I don't think you should be messing with strict application. It's very rarely needed.Crossquestion
M
7

Argument against

I found a proposal from 2008 in haskell-prime to make the $ and $! operators left-associative:

https://ghc.haskell.org/trac/haskell-prime/wiki/ChangeDollarAssociativity

There is only one argument against the proposal: "This would break a lot of code".

Arguments in favour

Instead, there are given four arguments in favour of left-associative ($), the last one being the same as yours, and considered the most important. They are, in short:

  • 0) given the expression f x y, with two applications, we would be able to write f $ x $ y

  • 1) now, with right associative ($), we can write f . g . h $ x as f $ g $ h $ x,

    however: \x -> f $ g $ h $ x ==> f $ g $ h is invalid,

    so that writing such pipelines with composition is better, as it allows easier cleanup of code

  • 2) Left associative ($) allows you to eliminate more parentheses, in addition to the ones eliminated with (.), for instance:

    f (g x) (h y) ==> f $ g x $ h y

  • 3) your argument: the right associative version of $! is inconvenient because of giving rise to things like: ((f $! x) $! y) $! z instead of f $! x $! y $! z

Conclusion

I give support to use the better left-associative version of application operators redefining them at the beginning of our code, like this:

import Prelude hiding (($), ($!))

infixl 0  $, $!
($), ($!) :: (a -> b) -> a -> b  
f $  x =         f x
f $! x = x `seq` f x
Merriemerrielle answered 25/12, 2014 at 3:41 Comment(5)
Older (2006), similar discussion in Haskell Cafe (he tells: "the associativity of $ is just plain wrong"): mail-archive.com/[email protected]/msg12549.htmlMerriemerrielle
To translate an expression in the conventional style f $! g $! x with the cited tactic for plain $ , one would need some sort of strict composition: f .! g $! x. I wonder: is there such operator already defined in a library?Jere
BTW, the current <$> is consistent with the current conventional $: f <$> g <$> x seems to be equivalent to f . g <$> x. But another, left-associative version of <$> wouldn't make much sense, because consuming several Applicative arguments is written as f <$> x <*> y or g <*> x <*> y (for a pure f or an Applicative g). It seems that <*> is already left-associative (as wanted for $ in Haskell-prime), and lower priority than <$>.Jere
It seems that <$> is left-associative in the latest base (so, inconsistent with the conventional $), contrary to what I said in the above comment. But my <$> from an older base I have on my system is right associative! (show <$> show <$> Just 3 gives Just "\"3\"" for me; or I don't understand what is happening, so I asked a question)Jere
Yes, there exists (.!): Strict composition.Jere
C
11

It's to mirror the fixity of $. You could make a very good case for both $ and $! having the wrong fixity.

Crossquestion answered 9/5, 2014 at 17:29 Comment(9)
What is $? I googled "haskell operators" but none of the first couple google links mention it (even the one that's a PDF file containing a list of haskell operators). Neither has the book I'm reading mentioned it so far (Real World Haskell). Is there a list of all Haskell operators somewhere?Swill
@Swill #940882Gory
@Swill You'll even find a link to the author of Real World Haskell commenting on its use in the book in Thomas' comment.Evanish
Sorry, I should ask my questions one at a time. Where can I find a list of Haskell operators?Swill
The Prelude operators are in the Haskell report.Crossquestion
@Swill Do note that there's no such thing as a list of Haskell operators. Is *%^*%^*&&$&%^ a Haskell operator? Well, it could be, if some library defined it.Etymon
Sorry, I meant pre-defined operatorsSwill
@Swill To search for Haskell operators and functions by name try Hoogle (uses a limited set of packages, but can also search by type which is very useful) or Hayoo (searches only by name, but in all of Hackage.)Hardboard
@Swill FP Complete's Hoogle searches a larger number of packages than the regular Hoogle, so it can be handy fpcomplete.com/hoogleDucat
M
7

Argument against

I found a proposal from 2008 in haskell-prime to make the $ and $! operators left-associative:

https://ghc.haskell.org/trac/haskell-prime/wiki/ChangeDollarAssociativity

There is only one argument against the proposal: "This would break a lot of code".

Arguments in favour

Instead, there are given four arguments in favour of left-associative ($), the last one being the same as yours, and considered the most important. They are, in short:

  • 0) given the expression f x y, with two applications, we would be able to write f $ x $ y

  • 1) now, with right associative ($), we can write f . g . h $ x as f $ g $ h $ x,

    however: \x -> f $ g $ h $ x ==> f $ g $ h is invalid,

    so that writing such pipelines with composition is better, as it allows easier cleanup of code

  • 2) Left associative ($) allows you to eliminate more parentheses, in addition to the ones eliminated with (.), for instance:

    f (g x) (h y) ==> f $ g x $ h y

  • 3) your argument: the right associative version of $! is inconvenient because of giving rise to things like: ((f $! x) $! y) $! z instead of f $! x $! y $! z

Conclusion

I give support to use the better left-associative version of application operators redefining them at the beginning of our code, like this:

import Prelude hiding (($), ($!))

infixl 0  $, $!
($), ($!) :: (a -> b) -> a -> b  
f $  x =         f x
f $! x = x `seq` f x
Merriemerrielle answered 25/12, 2014 at 3:41 Comment(5)
Older (2006), similar discussion in Haskell Cafe (he tells: "the associativity of $ is just plain wrong"): mail-archive.com/[email protected]/msg12549.htmlMerriemerrielle
To translate an expression in the conventional style f $! g $! x with the cited tactic for plain $ , one would need some sort of strict composition: f .! g $! x. I wonder: is there such operator already defined in a library?Jere
BTW, the current <$> is consistent with the current conventional $: f <$> g <$> x seems to be equivalent to f . g <$> x. But another, left-associative version of <$> wouldn't make much sense, because consuming several Applicative arguments is written as f <$> x <*> y or g <*> x <*> y (for a pure f or an Applicative g). It seems that <*> is already left-associative (as wanted for $ in Haskell-prime), and lower priority than <$>.Jere
It seems that <$> is left-associative in the latest base (so, inconsistent with the conventional $), contrary to what I said in the above comment. But my <$> from an older base I have on my system is right associative! (show <$> show <$> Just 3 gives Just "\"3\"" for me; or I don't understand what is happening, so I asked a question)Jere
Yes, there exists (.!): Strict composition.Jere

© 2022 - 2024 — McMap. All rights reserved.