On Wed, Jun 24, 2009 at 11:13 PM, Hector Guilarte <hectorg87@gmail.com> wrote:

Thanks! Actually,  if I understood well what you proposed, that's how I first tought of doing it, but with a [Maybe String] and only append whenever I actually had a (Just string), but as I said before, I don't think my teacher is gonna like that solution since it is not going to print when the interpreter finds the show instruction in the GCL code, it is gonna wait until it finishes to interpret the whole code and then print everything.

Not true!  Haskell is lazy.  You just have to think about program evaluation inside out.  So it's not "print when you come across this instruction", but rather "run the program just far enough to print the first line".

That's would be ok with me, but actually in a language point of view that wouldn't be to usefull, since trying to debug a program printing flags couldn't be done (and I'm not doing a debbuger for it). I know my language is not gonna be used for real, but I'm sure that would be my teacher's argument to tell me I can't do it that way. Still, I sent him an e-mail asking if it can be done like that just in case.

I assume that Haskell is your language choice, not the teacher's.  In which case it may be very hard to convince the teacher that this is correct, if he is used to thinking in an imperative style.  Nonetheless, you chose a functional language and it is only fair to solve the program in a functional way, right?  Haskell tries to be a language with no side effects at all, it just "accidentally" falls short here and there; if it achieves its goal, there would be no correct way to solve it by your alleged teacher's argument.



If I didn't understand what you said, can you explain it again please?

I think you've got it, except for the understanding that lists are lazy so "running the program" is equivalent to asking for elements from the list.
 

If I did then, does anybody knows how to print on the screen in the moment the show instruction is interpreted that guarantees that my code is gonna be "safe"

That is a very hard thing to ask of a pure language, which does not really concern itself with such questions.  "The moment the show instruction is interpreted" is abstracted away from the Haskell programmer, so that the compiler may choose to evaluate it any time it pleases (as long as it gives you the answer you asked for).


Also, nobody has told me why I shouldn't just use my original solution using unsafePerformIO, is it really bad? is it dangerous? why is it "unsafe"?

It is contrary to the spirit of Haskell, and breaks invariants that reasoning in the language relies on.  It is not technically "dangerous", i.e. your program will still "work", but you will be contested here and there about whether it should be considered correct.  If you published a Haskell module which used such a trick to the community, you would have a very hard time convincing people to use it.

The invariant it breaks is called "referential transparency", or maybe "purity" (those terms are kind of muddled together the way I look at things).  Either way, consider the following program:

mult2 x = 2*x
main = do
    print (mult2 21)
    print (mult2 21)

Now, functions are in the mathematical sense in Haskell, so the result of a function is entirely determined by its arguments.  That means, without considering anything about the definition of mult2, refactor main into:

main = do
    let answer = mult2 21
    print answer
    print answer

And we know that this program will behave exactly the same.

However, if mult2 were instead:

mult2 x = unsafePerformIO $ do { print x; return (2*x) }

Then the former program would probably print 21,42,21,42,  whereas the latter would print 21,42,42.  Thus our correct transformation of programs changed behavior. 

Haskell programmers rely on this sort of refactoring all the time, and unsafePerformIO has the potential to break it.  That is why it's unsafe.

Safe uses of unsafePerformIO are those where any such transformation won't change the overall behavior of the program.  They do exist, and are usually employed for optimization purposes.  But yours is not such a case; your unsafePerformIO has observable side-effects.

The "list of strings" solution is the Haskell way to solve this problem.  If your teacher does not accept the solution, then your teacher is not actually letting you program in Haskell.

Cheers,
Luke