About print and side-effects

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

About print and side-effects

Daniel Carrera-2
Hi all,

The recent responses to my first question (thanks guys!) included the
following bit:

main = print (fact 42)


Now, print is a side-effect. Shouldn't it involve a do-block or a nomad
or one of those scary things you hear about when learning about side
effects in functional programs? How come 'print' is allowed to exist
alone if it's a side-effect?

Thanks for the help.

Cheers,
Daniel.
--
      /\/`) http://oooauthors.org
     /\/_/  http://opendocumentfellowship.org
    /\/_/
    \/_/    I am not over-weight, I am under-tall.
    /
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: About print and side-effects

Anders Höckersten
sön 2005-12-18 klockan 20:22 +0000 skrev Daniel Carrera:

> Hi all,
>
> The recent responses to my first question (thanks guys!) included the
> following bit:
>
> main = print (fact 42)
>
>
> Now, print is a side-effect. Shouldn't it involve a do-block or a nomad
> or one of those scary things you hear about when learning about side
> effects in functional programs? How come 'print' is allowed to exist
> alone if it's a side-effect?
>
> Thanks for the help.
>
> Cheers,
> Daniel.
Daniel, first of all I would like to invite you to #haskell on
irc.freenode.net. There are almost always people there to answer quick
questions like this one, with less of the waiting period that's involved
in a mailing list. You are of course also welcome to continue asking
your questions here if you prefer.

To answer your question: Yes, your main function does in fact involve
the IO monad. You can easily check the type of main or any function you
write by typing for example ":t main" in GHCi or Hugs. If you do this,
you will see that main has the type signature "main :: IO ()". The
reason you don't need do-blocks for this particular function is because
it only involves one computation. If you have more than one, you need
do-notation (well, there's a more correct and longer explanation for all
this, but we can save that one for later).

Oh, and don't mistake monads for scary things, they are really quite
warm and fuzzy once you get to know them. :)

Regards,
Anders

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

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

Re: About print and side-effects

haskell-2
In reply to this post by Daniel Carrera-2

Daniel Carrera wrote:
> Hi all,
>
> The recent responses to my first question (thanks guys!) included the
> following bit:
>
> main = print (fact 42)

You can use a "do" block:

main = do
          print (fact 42)

which also works.

But for a single thing of type (IO _) the "do" is optional.

>
>
> Now, print is a side-effect. Shouldn't it involve a do-block or a nomad
> or one of those scary things you hear about when learning about side
> effects in functional programs? How come 'print' is allowed to exist
> alone if it's a side-effect?
>
> Thanks for the help.
>
> Cheers,
> Daniel.

By nomad you seemed to either be ridiculing or misspelling monad. The
right-hand-side of main must have type "IO _" where _ is whatever type
you program returns, often "()".  The print command has type "print ::
forall a. (Show a) => a -> IO ()" so the type of "print (fac 42)" is the
desired type "IO ()".  Thus there is no need for special "do" syntax or
monad operators >> or >>=.

Lets say you want to print several values:

main = do putStr "(fact 42) is "
          print (fact 42)
          putStr "(fact 1) is "
          print (fact 1)

That is the do-syntax with the whitespace sensitive 2D layout syntax.

This is equivalent to

main = do { putStr "(fac 42) is ";  print (fact 42);
 putStr "(fac 1) is "; print (fact 1); }

Now do-syntax is just sugar for (slighty simplified here):

main = putStr "(fac 42) is " >>  print (fact 42) >>
       putStr "(fac 1) is "">> print (fact 1)

Where >> is an infix, binary operator that takes commands and returns
the concatenated command.  So the above is a single action that is the
concatenation of the four IO commands.

Since it is now a single command, no "do" is needed.

The value of the whitespace form is that some people are happier reading
and writing it.  The value of the {;} syntax is that it is very familiar
and perhaps more pleasing to some people and perhaps more pleasing to
some code generaion tools.  The value of the de-sugared form is that it
*is* the Monadic form (which acutally uses >>= and case statements,
details in the language definition
http://www.informatik.uni-freiburg.de/~thiemann/haskell/haskell98-report-html/exps.html#sect3.14
)

Sometime the Monadic form can be used to remove unhelpful variable
bindings that clutter code.  This can lead to clearer code.

Note that the whitespace layout form has much less punctuation, and only
a single two letter keyword.  Unlike python the decision about how much
to indent is up to the author, but the command must be lined up.

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

Re: About print and side-effects

Daniel Carrera-2
Chris Kuklewicz wrote:
> By nomad you seemed to either be ridiculing or misspelling monad.

Misspelling. It's a new word for me. I'm not really sure what it means.
I expect it'll take me a while to figure it out.

Thank you for the help.

Best,
Daniel.
--
      /\/`) http://oooauthors.org
     /\/_/  http://opendocumentfellowship.org
    /\/_/
    \/_/    I am not over-weight, I am under-tall.
    /
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: About print and side-effects

Sebastian Sylvan
On 12/18/05, Daniel Carrera <[hidden email]> wrote:
> Chris Kuklewicz wrote:
> > By nomad you seemed to either be ridiculing or misspelling monad.
>
> Misspelling. It's a new word for me. I'm not really sure what it means.
> I expect it'll take me a while to figure it out.

It sounds scary, I know!
For now I'd recommend you to just think of it as "A computation, which
may have side-effects, returning a value". And consider the
do-notation as a way to "merge multiple computations together into a
single one".
For instance, "print" is a computation taking a showable value,
returning () with the side effect that a string representation of the
value is printed to stdout.

Writing an IO program is then easily conceptualised as just "merging"
together several existing IO computations into a single one. The
compiler will take care of generating code for actually *running* the
IO computation, your job is to define it.

Monads have more uses than this, and there's a bit of interesting
things to think about when learning about them, but you should
probably hold off on that for now.

/S

--
Sebastian Sylvan
+46(0)736-818655
UIN: 44640862
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe