1

I have the following (from here):

for_ [1..10] $ (\x -> T.putStrLn $ T.pack $ show x )

I'm trying to rewrite this in terms more like

applylike myfunction toList

rather than

applylike tolist myfunction

I understand the flip function can be employed to change argument order:

flip :: (a -> b -> c) -> b -> a -> c

flip f takes its (first) two arguments in the reverse order of f.

>>> flip (++) "hello" "world"
"worldhello"

This works as my original:

import Data.Foldable (for_)

:t flip
-- 1
for_ [1..10] $ (\x -> T.putStrLn $ T.pack $ show x )
-- success

But when I try to apply it directly, this fails:

-- 2
flip for_ $ (\x -> T.putStrLn $ T.pack $ show x ) [1..10] 
-- fail

I notice, however, that if I remove the $ operator which was required in (1), it succeeds:

-- 3
flip for_ (\x -> T.putStrLn $ T.pack $ show x ) [1..10] 
-- success

But I don't understand why that scans correctly. When I remove the $ operator from the original non-flipped version (1), that also fails.

-- 4    
for_ [1..10] (\x -> T.putStrLn $ T.pack $ show x )
-- fail

How are these being parsed that $ is required in (1) and required not to be present in (3)?

Update

Apologies: 4 above does succeed. I must have had a typo while investigating this, which certainly added to my confusion. For future readers, 4 does not fail and the universe makes more sense, and both comments and the answer accepted below were very helpful in this investigation.

Mittenchops
  • 18,633
  • 33
  • 128
  • 246

1 Answers1

4

Because that's how the $ operator works. This operator is not part of Haskell syntax, but a regular user-defined operator, like any other. It's defined like this:

f $ x = f x

Therefore, if you write something like:

f a $ b

That is the same as:

f a b

But if you write something like:

f $ a b

That is the same as:

f (a b)

This is because function application a b (i.e. function a applied to argument b) has the highest precedence in Haskell, nothing can bind stronger than the function application, including the $ operator.

Therefore, your first attempt:

flip for_ $ (\x -> T.putStrLn $ T.pack $ show x ) [1..10] 

Is really equivalent to:

flip for_ ( (\x -> T.putStrLn $ T.pack $ show x ) [1..10] )

Which is clearly not what you meant.

Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172
  • a side note, ($) actually binds the weakest: `*Main> :i ($)` says `infixr 0 $` i.e. level 0, while the functional application (i.e. "space") binds at the level 10. – Will Ness Apr 29 '19 at 18:30