
On Thu, 2005-06-23 at 00:17 -0400, kynn@panix.com wrote:
printFact [] = return printFact (x:xs) = do -- triggers error message putStrLn (x ++ " factorial is " ++ fact x) printFact xs return
If anyone can explain to me how to fix this error I'd appreciate it.
You forgot to return a value. Typically when you have a function which performs IO, but you don't want to return anything special as its result you return the unit value, written as: (). printFact [] = return () printFact (x:xs) = do -- triggers error message putStrLn (x ++ " factorial is " ++ fact x) printFact xs return () Another problem with this code is that you are trying to append numbers with strings: x ++ " factorial is " ++ fact x You will need to convert the numbers to strings explicitly with show: show x ++ " factorial is " ++ show (fact x)
Also, what is the difference between <- and let?
The key difference is that, in the do notation, <- is used exclusively with monads, whereas, let can be used with arbitrary types. The left argument to <- is some kind of pattern (most often just a single variable), and the right argument is a monadic expression. Eg: x <- getLine means roughly: _run_ getLine, which returns an (IO String) type, and bind the actual String to x, whatever the String happens to be in this instance. Note carefully, that getLine has type (IO String) but x has type String. The let keyword is just an ordinary polymorphic binding, eg let x = 5 + y says x is equal to the expression "5 + y" from now on, until the end of the do block, or another binding of x is introduced. Note carefully that if (5 + y) has type Int (for argument's sake), then x also has type Int. Note that for let, unlike <-, the right argument is an arbitrary expression, it does not have to be a monadic one. What might be confusing is that you can write: let z = getLine which is not the same as: z <- getLine The former just makes z equal to getLine, the latter _runs_ getLine, unpacks the IO result, and binds it to z. You might benefit from looking at how do notation is desugared into ordinary expressions, this might help demystify some of it. Take a look at the Haskell Report: http://www.haskell.org/onlinereport/exps.html#sect3.14
Lastly, any comments on any other detail of the code, particularly coding, style are most welcome.
Once you become familiar with Haskell you will learn that some patterns are idiomatic and can be simplified with the use of library functions. For instance, many operations over lists can be achieved with a map, or a fold. Also there are some useful versions of these for monads, such as mapM and foldM. Reading other people's code sometimes helps. Cheers, Bernie.