Ruby Quiz Solution #15 - won't work after compilation

If I call "main" in ghci, my program runs as it should, but if I try compiling it, and then running the result of that compilation, i.e.: $ ghc -o animal_game game.hs $ ./animal_game unexpected things occur, particularly "getChar" does not work correctly, and if I take a route that doesn't lead to getChar needing to be called, the program stops running at the end of 2nd run despite your response to the do-you-want-to-play-again-question. $ ./animal_game .... Do you want to play again? (y/n) y .... Do you want to play again? (y/n) y Thanks for playing! $ The source code is here: http://rafb.net/p/7fYlEV72.html I don't know how long that will stay up there, so let me know if it's gone and I'll repaste or find a better alternative. What would also be nice is any comments on the actual code; as a begginner, it's nice to get some feedback, and I might as well also ask the following question. Originally I wanted to the types to be as such: data Animal = Animal String data Question a b = Question String a b -- where a is a Question or an Animal, as is b The problem is I wanted methods that had types that were able to accept an argument of type Animal or Question, and for it to act appropriately on that type, I tried adding them to common type classes (a new one I created called 'Askable' which contained a method 'ask'), but I ran into a whole bunch of problems. Is there any easy way to do it?

On Thu, Aug 14, 2008 at 03:33:26PM +0100, Alex Watt wrote:
If I call "main" in ghci, my program runs as it should, but if I try compiling it, and then running the result of that compilation, i.e.:
$ ghc -o animal_game game.hs $ ./animal_game
unexpected things occur, particularly "getChar" does not work correctly, and
When you say 'getchar does not work correctly', exactly what do you mean? I'm not sure of the problem, but this smells to me of something having to do with buffering and/or newline characters not getting handled properly.
What would also be nice is any comments on the actual code; as a begginner, it's nice to get some feedback, and I might as well also ask the following question. Originally I wanted to the types to be as such:
data Animal = Animal String data Question a b = Question String a b -- where a is a Question or an Animal, as is b
The problem is I wanted methods that had types that were able to accept an argument of type Animal or Question, and for it to act appropriately on that type, I tried adding them to common type classes (a new one I created called 'Askable' which contained a method 'ask'), but I ran into a whole bunch of problems. Is there any easy way to do it?
Creating an 'Askable' type class sounds like it would be a great solution in certain instances; the problem to me looks like the fact that you want to create a data structure (a QuestionTree) which contains both Animals and Questions. This quickly leads into existential types---doable, but probably best left until later. At any rate, your current solution---making Animal and Question constructors of a data type, and implementing play' and other such functions by pattern matching---seems quite nice. It's certainly the approach I would take. In general your code looks very nice. The only comment I have is that I would separate out play' and getNewAnimal as separate top-level functions, rather than defining them in a 'where' block. Functions which are not top-level are difficult to test by themselves. -Brent

On Aug 14, 2008, at 15:13 , Brent Yorgey wrote:
On Thu, Aug 14, 2008 at 03:33:26PM +0100, Alex Watt wrote:
If I call "main" in ghci, my program runs as it should, but if I try compiling it, and then running the result of that compilation, i.e.:
$ ghc -o animal_game game.hs $ ./animal_game
unexpected things occur, particularly "getChar" does not work correctly, and
When you say 'getchar does not work correctly', exactly what do you mean? I'm not sure of the problem, but this smells to me of something having to do with buffering and/or newline characters not getting handled properly.
I'm thinking termios is in line mode still. System.Posix.Terminal is what he needs. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Brent: getChar acts like getLine from what I can tell, it's a bit odd
On 8/14/08, Brandon S. Allbery KF8NH
On Aug 14, 2008, at 15:13 , Brent Yorgey wrote:
On Thu, Aug 14, 2008 at 03:33:26PM +0100, Alex Watt wrote:
If I call "main" in ghci, my program runs as it should, but if I try compiling it, and then running the result of that compilation, i.e.:
$ ghc -o animal_game game.hs $ ./animal_game
unexpected things occur, particularly "getChar" does not work correctly, and
When you say 'getchar does not work correctly', exactly what do you mean? I'm not sure of the problem, but this smells to me of something having to do with buffering and/or newline characters not getting handled properly.
I'm thinking termios is in line mode still. System.Posix.Terminal is what he needs.
-- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Am Donnerstag, 14. August 2008 22:12 schrieb Alex Watt:
Brent: getChar acts like getLine from what I can tell, it's a bit odd
Buffering indeed, in ghci, IIRC, stdin and stdout aren't buffered by default, for binaries the default is line buffering, so the char won't be gotten until you type a newline. Changing your code to module Main where import System.IO main :: IO () main = do hSetBuffering stdin NoBuffering play (Animal "Dog") return () solves the problem: Think of an animal, I will try to guess what it is... Are you thinking of a Dog? (y/n) n I give up, you win! Please help me improve my guesses! What is the name of the animal you were thinking of? Cat Now please enter a question that answers yes for a Cat and no for a Dog Does it meow? Do you want to play again? (y/n) y Think of an animal, I will try to guess what it is... Does it meow? (y/n) n Are you thinking of a Dog? (y/n) n I give up, you win! Please help me improve my guesses! What is the name of the animal you were thinking of? Cow Now please enter a question that answers yes for a Cow and no for a Dog Is it useful? Do you want to play again? (y/n) y Think of an animal, I will try to guess what it is... Does it meow? (y/n) n Is it useful? (y/n) y Are you thinking of a Cow? (y/n) y I win this time. Do you want to play again? (y/n) n Thanks for playing.. On the other count, I have to agree with Brent, the code is very nice overall, but play' and getNewAnimal as top level functions would be better, and I don't really like the line play' question@(Question s y n) = do ans <- ask $ show question I'd prefer do ans <- ask s but that's purely a matter of taste. HTH, Daniel

Thanks Daniel, that worked brilliantly.
I took yours and Brent's advice and brought play' and
getNewAnimal out of the where block. Also, the line "do ans <- ask $ show
question" was probably there due to some of the previous code, in which case
that line would have been slightly better (in my opinion, anyway), but I've
changed it now, because I prefer "do ans <- ask s" too.
Thanks again.
- Alex
On 8/14/08, Daniel Fischer
Am Donnerstag, 14. August 2008 22:12 schrieb Alex Watt:
Brent: getChar acts like getLine from what I can tell, it's a bit odd
Buffering indeed, in ghci, IIRC, stdin and stdout aren't buffered by default, for binaries the default is line buffering, so the char won't be gotten until you type a newline. Changing your code to
module Main where
import System.IO
main :: IO () main = do hSetBuffering stdin NoBuffering play (Animal "Dog") return ()
solves the problem:
Think of an animal, I will try to guess what it is... Are you thinking of a Dog? (y/n) n I give up, you win! Please help me improve my guesses! What is the name of the animal you were thinking of? Cat Now please enter a question that answers yes for a Cat and no for a Dog Does it meow?
Do you want to play again? (y/n) y
Think of an animal, I will try to guess what it is... Does it meow? (y/n) n Are you thinking of a Dog? (y/n) n I give up, you win! Please help me improve my guesses! What is the name of the animal you were thinking of? Cow Now please enter a question that answers yes for a Cow and no for a Dog Is it useful?
Do you want to play again? (y/n) y
Think of an animal, I will try to guess what it is... Does it meow? (y/n) n Is it useful? (y/n) y Are you thinking of a Cow? (y/n) y I win this time.
Do you want to play again? (y/n)
n Thanks for playing..
On the other count, I have to agree with Brent, the code is very nice overall, but play' and getNewAnimal as top level functions would be better, and I don't really like the line
play' question@(Question s y n) = do ans <- ask $ show question
I'd prefer do ans <- ask s
but that's purely a matter of taste.
HTH,
Daniel
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (4)
-
Alex Watt
-
Brandon S. Allbery KF8NH
-
Brent Yorgey
-
Daniel Fischer