do notation, pattern matching, if, & case

I'm working on a cli program where I'd like to take input from a file or stdin. I've managed to get my program to work but thought my dispatch mechanism could be simplified. I use a scheme along the lines of f in the following minimal example, which compiles. However, if I try to use f' or f'', I get parse errors. Three questions: * Is there a better way of doing this * Are stylistic changes to f really called for? * How can/ought I correct my syntax errors? Many thanks, vale
module MinimalExample where import System.IO (getContents)
f :: String -> IO () f "-" = do s <- getContents putStrLn s f file = do s <- readFile file putStrLn s
-- f' :: String -> IO () -- f' file = do -- if file == "-" -- then s <- getContents -- else s <- readFile file -- putStrLn s
-- f'' :: String -> IO () -- f'' file = do -- case file of -- "-" -> s <- getContents -- _ -> s <- readFile file -- putStrLn s
-- vale cofer-shabica vale.cofershabica@gmail.com

On Tue, Aug 26, 2014 at 2:16 PM, Vale Cofer-Shabica < vale.cofershabica@gmail.com> wrote:
However, if I try to use f' or f'', I get parse errors. Three questions:
* Is there a better way of doing this * Are stylistic changes to f really called for? * How can/ought I correct my syntax errors?
if and case are expressions. As such they are not part of the outer "do"'s syntax; you would need a new "do" in each one. This will make more sense if you study how "do" is converted to uses of the (>>) and (>>=) operators. Additionally you can't just use "s <- getContents" like that, since (a) "s" will go out of scope, abnd (b) with nothing following, it expands to a syntax error ("getContents >>= \s ->" with nothing after the "->"). Since if and case are expressions, you need to produce a result from them and bind it at the top level. So you really want something like: f' :: String -> IO () f' file = do s <- if file == "-" then getContents else readFile file putStrLn s -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

Thank you!
I was able to re-write the case-of version as well so it compiles too.
I'll read up on de-sugaring do-notation.
-vale
--
vale cofer-shabica
vale.cofershabica@gmail.com
401.267.8253
On Tue, Aug 26, 2014 at 2:23 PM, Brandon Allbery
On Tue, Aug 26, 2014 at 2:16 PM, Vale Cofer-Shabica
wrote: However, if I try to use f' or f'', I get parse errors. Three questions:
* Is there a better way of doing this * Are stylistic changes to f really called for? * How can/ought I correct my syntax errors?
if and case are expressions. As such they are not part of the outer "do"'s syntax; you would need a new "do" in each one. This will make more sense if you study how "do" is converted to uses of the (>>) and (>>=) operators.
Additionally you can't just use "s <- getContents" like that, since (a) "s" will go out of scope, abnd (b) with nothing following, it expands to a syntax error ("getContents >>= \s ->" with nothing after the "->"). Since if and case are expressions, you need to produce a result from them and bind it at the top level. So you really want something like:
f' :: String -> IO () f' file = do s <- if file == "-" then getContents else readFile file putStrLn s
-- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (2)
-
Brandon Allbery
-
Vale Cofer-Shabica