Those damned parentheses

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

Those damned parentheses

Eitan Goldshtrom
Hi. I am kind of tired of all of the parentheses I have to put in places and I'm trying to figure out what is the correct way to write code such that I can leave out parentheses. For example, I have the following:

data Message = ... --leaving this out because it's not important
data Plane = Plane {
  id          :: Int,
  position    :: (Int,Int,Int),
  direction   :: Int,
  path        :: [Int],
  messagebuf  :: Chan Message
  }

main = do
  c <- newChan :: Chan Message
  p <- Plane 0 (0,0,0) 0 [] c
  f p

f p = putStrLn $ (show Main.id p) ++ " - message received"

This causes an error "The function `show' is applied to two arguments". If I put instead:
f p = putStrLn $ (show . Main.id p) ++ " - message received"

I get the error "Couldn't match expected type `[Char]' with actual type `a0 -> c0'". The only way it seems to work is
f p = putStrLn $ (show (Main.id p)) ++ " - message received"

This seems to be the same for many other situations where I try to use function composition of some sort. It's just getting kind of annoying.

-Eitan

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Brandon Allbery
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 5/7/11 15:10 , Eitan Goldshtrom wrote:
> I get the error "Couldn't match expected type `[Char]' with actual type `a0
> -> c0'". The only way it seems to work is
> f p = putStrLn $ (show (Main.id p)) ++ " - message received"

Interestingly enough, you have the correct answer in there as well:  "$"

> f p = putStrLn $ (show $ Main.id p) ++ " = message received"

You may also want to look into Control.Applicative.

- --
brandon s. allbery     [linux,solaris,freebsd,perl]    [hidden email]
system administrator  [openafs,heimdal,too many hats]                kf8nh
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk3FmykACgkQIn7hlCsL25X9cQCeM2leHUslCJWW1GIFKtt5Dw9P
gFoAn1DbWu9QO89062Dx6hMIPRNq6siU
=P2Zz
-----END PGP SIGNATURE-----

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Antoine Latter-2
In reply to this post by Eitan Goldshtrom
On Sat, May 7, 2011 at 2:10 PM, Eitan Goldshtrom <[hidden email]> wrote:

> Hi. I am kind of tired of all of the parentheses I have to put in places and
> I'm trying to figure out what is the correct way to write code such that I
> can leave out parentheses. For example, I have the following:
>
> data Message = ... --leaving this out because it's not important
> data Plane = Plane {
>   id          :: Int,
>   position    :: (Int,Int,Int),
>   direction   :: Int,
>   path        :: [Int],
>   messagebuf  :: Chan Message
>   }
>
> main = do
>   c <- newChan :: Chan Message
>   p <- Plane 0 (0,0,0) 0 [] c
>   f p
>
> f p = putStrLn $ (show Main.id p) ++ " - message received"
>

One thing to keep in mind is that function application binds tightest,
and function application goes from left to right, so:

> a b c d

is parsed as:

> ((a b) c) d

I'm not really sure what you're doing, but I would probably write it as:

> f p = putStrLn $ show (Main.id p) ++ " - message received"

Because function application binds tightest, I don't need parenthesis
around the (show ...) part.

The other rule to note is the the ($) function binds the weakest of
them all, so you can do a lot to the left of it and to the right of it
without parentheses.

> This causes an error "The function `show' is applied to two arguments". If I
> put instead:
> f p = putStrLn $ (show . Main.id p) ++ " - message received"
>
> I get the error "Couldn't match expected type `[Char]' with actual type `a0
> -> c0'". The only way it seems to work is
> f p = putStrLn $ (show (Main.id p)) ++ " - message received"
>
> This seems to be the same for many other situations where I try to use
> function composition of some sort. It's just getting kind of annoying.
>
> -Eitan
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Eitan Goldshtrom
In reply to this post by Brandon Allbery
I know about the $ symbol, that's why it's in there in the respective
places. I see that I can use it to fix my problem, but I was trying to
figure out function composition really. I guess that's just not the
place for it. I'll check out Control.Applicative. Also thanks for the
clarification on function application. I know functions are by default
infixl 9, but I hadn't really thought that through all the way.
-Eitan

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Felipe Lessa
As another suggestion, you may try HLint [1].  It usually tells you if
you put unnecessary parenthesis.  Among other nice suggestions.

[1] http://community.haskell.org/~ndm/hlint/  (or cabal-install hlint)

Cheers, =)

--
Felipe.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

wren ng thornton
In reply to this post by Eitan Goldshtrom
On 5/7/11 4:29 PM, Eitan Goldshtrom wrote:
> I know about the $ symbol, that's why it's in there in the respective
> places. I see that I can use it to fix my problem, but I was trying to
> figure out function composition really. I guess that's just not the
> place for it. I'll check out Control.Applicative. Also thanks for the
> clarification on function application. I know functions are by default
> infixl 9, but I hadn't really thought that through all the way.

The "secret" to parentheses in Haskell is that juxtaposition binds most
strongly. That's it. Other languages (e.g., Perl, ML) have much more
complicated rules which often lead new Haskellers astray; ignore them!

Thus,

     f p = putStrLn $ show (Main.id p) ++ " - message received"

Because you are applying Main.id to p, and you are applying show to
(Main.id p). Of course, this is identical to:

     f p = putStrLn (show (Main.id p) ++ " - message received")

Since ($) is defined by:

     f $ x = f x

with very low precedence. Alternatively, these are also identical to:

     f p = putStrLn $ (show . Main.id) p ++ " - message received"

     f p = putStrLn $ ((show . Main.id) p) ++ " - message received"

     f p = putStrLn $ (show . Main.id $ p) ++ " - message received"

     f p = putStrLn ((show . Main.id $ p) ++ " - message received")

etc. Note that the definition of (.) is:

     f . g = \x -> f (g x)

or, if you prefer,

     (f . g) x = f (g x)

--
Live well,
~wren

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Yitzchak Gale
Eitan Goldshtrom wrote:
>> f p = putStrLn $ (show (Main.id p)) ++ " - message received"

Brandon S Allbery KF8NH wrote:
> f p = putStrLn $ (show $ Main.id p) ++ " = message received"

wren ng thornton <[hidden email]> wrote:
>    f p = putStrLn $ show (Main.id p) ++ " - message received"
>    f p = putStrLn $ (show . Main.id) p ++ " - message received"
>    f p = putStrLn $ ((show . Main.id) p) ++ " - message received"
>    f p = putStrLn $ (show . Main.id $ p) ++ " - message received"
>    f p = putStrLn ((show . Main.id $ p) ++ " - message received")
> etc.

I think the clearest way to write it is:

f = putStrLn . (++ " - message received") . show . Main.id

Not because it happens to be point-free, but because it is
the "combinator" approach. You apply functions one after
the other, each with its own simple meaning and purpose.

If I were to describe to someone in words what this
function does, I would say something like: "Apply Main.id,
turn it into a string, tack a message onto the end, and
print it." So why not write it that way in Haskell?

One of the nicest features of Haskell is that the
combinator approach is often so natural.

Regards,
Yitz

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Andrew Butterfield

On 10 May 2011, at 08:30, Yitzchak Gale wrote:


If I were to describe to someone in words what this
function does, I would say something like: "Apply Main.id,
turn it into a string, tack a message onto the end, and
print it." So why not write it that way in Haskell?

Why not indeed ?

(-->) = flip (.)

f = Main.id --> show --> (++ " = message received") --> putStrLn

;-)



One of the nicest features of Haskell is that the
combinator approach is often so natural.

:-) :-)


Regards,
Yitz

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

--------------------------------------------------------------------
Andrew Butterfield     Tel: +353-1-896-2517     Fax: +353-1-677-2204
Foundations and Methods Research Group Director.
School of Computer Science and Statistics,
Room F.13, O'Reilly Institute, Trinity College, University of Dublin
                            http://www.cs.tcd.ie/Andrew.Butterfield/
--------------------------------------------------------------------


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Roel van Dijk-3
On 10 May 2011 09:47, Andrew Butterfield <[hidden email]> wrote:
> Why not indeed ?
> (-->) = flip (.)
> f = Main.id --> show --> (++ " = message received") --> putStrLn

-- (>>>) :: Category cat => cat a b -> cat b c -> cat a c

import Control.Category ( (>>>) )
f = Main.id >>> show >>> (++ " - message received") >>> putStrLn

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Yitzchak Gale
Andrew Butterfield wrote:
>> Why not indeed ?

Roel van Dijk wrote:
> import Control.Category ( (>>>) )
> f = Main.id >>> show >>> (++ " - message received") >>> putStrLn

Indeed, I agree. I sometimes do that, too, when I want to
emphasize the idea of "applying tools one after the other".

But most often I just use traditional "function composition"
notation. That reminds us of the connection with mathematical
functions. It also raises less eyebrows when other people read
my code and see

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Yitzchak Gale
Andrew Butterfield wrote:
>> Why not indeed ?

Roel van Dijk wrote:
> import Control.Category ( (>>>) )
> f = Main.id >>> show >>> (++ " - message received") >>> putStrLn

Indeed, I agree. I sometimes do that, too, when I want to
emphasize the idea of "applying tools one after the other".

But most often I just use traditional "function composition"
notation. That reminds us of the connection with mathematical
functions. It also raises less eyebrows when other people read
my code - some people immediately panic when they see an
import from Control.Category or Control.Arrow. :)

Regards,
Yitz

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Those damned parentheses

Andrew Coppin
In reply to this post by Yitzchak Gale
On 10/05/2011 08:30 AM, Yitzchak Gale wrote:

> I think the clearest way to write it is:
>
> f = putStrLn . (++ " - message received") . show . Main.id

You're serious??

> If I were to describe to someone in words what this
> function does, I would say something like: "Apply Main.id,
> turn it into a string, tack a message onto the end, and
> print it." So why not write it that way in Haskell?

Hmm, I suppose.

OTOH, this breaks if you want to insert several items into a string. For
example,

   f x y z = putStrLn ("X = " ++ show x ++ ", Y = " ++ show y ++ ", Z =
" ++ show z)

(Fortunately, here a simple call to ($) will fix you up nicely.)

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe