let/where
There seem to be a few situations where it's not clear to me when to use let and when where. For instance, in this little example I was playing with to work out what syntax works, main = putStr (show (if maybe_index == Nothing then DP_Unknown else DP_Number index) ++ \n) where maybe_index = maybe_read word (Just index) = maybe_index or... main = let maybe_index = maybe_read word (Just index) = maybe_index in putStr (show (if maybe_index == Nothing then DP_Unknown else DP_Number index) ++ \n) Does anyone care? At the moment I use where so that at a first glance you get an overall idea of things, then you can read further for details if you like. I was disappointed to find that I don't seem to be able to write things like, main = let maybe_index = maybe_read word in putStr (show (if maybe_index == Nothing then DP_Unknown else DP_Number index) ++ \n) where (Just index) = maybe_index BTW, is the above a sane way of getting the 'index' 'out of' the Just? I often seem to be using a where (Just foo) = bar type of idiom. (Of course, there is that special let stuff for do notation too which doesn't seem to use in.) I hope all that was somewhat coherent, anyway, or at least sheds light on some of the confusion of newcomers to Haskell! -- Mark ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: let/where
On Wed, Sep 19, 2001 at 01:53:22PM -0400, Mark Carroll wrote: main = let maybe_index = maybe_read word in putStr (show (if maybe_index == Nothing then DP_Unknown else DP_Number index) ++ \n) where (Just index) = maybe_index BTW, is the above a sane way of getting the 'index' 'out of' the Just? I often seem to be using a where (Just foo) = bar type of idiom. I'd probably write this as something like main = case maybe_read word of Just index - putStrLn $ show $ if maybe_index == Nothing then DP_Unknown else DP_Number index Nothing - error No index found As for let versus where, I use whatever I think looks best, which tends to be where unless I have lots of nested ifs and cases. Ian ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: let/where
Yes, Haskell is a rather big language and unfortunately has much redundancy. It seems mostly to be a matter of taste which of `let' and `where' you prefer. Personally, I nearly always use `where' when possible (for the same reason you give); `let' only if the `where' would be too far away. However, for your example I would use `case': main = putStrLn . show $ case maybe_read word of Nothing - DP_Unkown Just index - DP_Number index (Another matter of tast: I don't like `_' in identifiers, but use capital letters like the Haskell Prelude) I was disappointed to find that I don't seem to be able to write things like, main = let maybe_index = maybe_read word in putStr (show (if maybe_index == Nothing then DP_Unknown else DP_Number index) ++ \n) where (Just index) = maybe_index No, the `let' is in the scope of the `where', but the `where' is not in the scope of the `let'. Expressions are nested and allowing mutual recursion here would make things really confusing. Ciao, Olaf -- OLAF CHITIL, Dept. of Computer Science, University of York, York YO10 5DD, UK. URL: http://www.cs.york.ac.uk/~olaf/ Tel: +44 1904 434756; Fax: +44 1904 432767 ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: let/where
The point of where is that it scopes over guards and multiple equations as well as right hand sides. f x | xsquared 1000 = xsquared | otherwise = 0 where xsquared = x*x For the same reason, it has to be restricted to appear at the top level of a right hand side. Of course, we also need a construct to bind local variables inside an expression -- hence let, which therefore cannot scope over guards. Two kinds of scope, two binding constructions. We could have got away with one, if we had thrown out guards and relied just on if-then-else to test conditions instead. But guards are very expressive: some programs would have been a lot harder to write without them. Typical examples are when we just want to pick out one case in the first equation of a function, before lots of pattern matching: f x y | simplecase x y = simpleanswer f p1 p2 = ... f p3 p4 = ... ... There's no neat way to write this with if-then-else: you need to split f into two functions f x y = if simplecase x y then simpleanswer else f' x y f' p1 p2 = ... ... That's the reason Haskell has two binding constructions. John Hughes ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: let/where
Norman Ramsey wrote: Was it not considered to forbid such ambiguous expressions, requiring explicit parentheses to resolve the ambiguity? Yes. At one time some expressions using infix operators at the same precedence had to be parenthesised if there was no natural associativity familiar from mathematics. From memory I think a `mod` b * c is an example. This caused some complaints and was quietly dropped. For let/where, my recollection is that the issue was raised and the solution agreed on the same day at one of the Glasgow meetings in '88. After that it was outside the domain of potentially ambiguous expression constructs and was not considered further. --brian ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: let/where
Thanks very much everyone, especially for the notes about the differences between let and where, and the uses of case and maybe! Someday it would be interesting to try a programming assignment and comparing my coding style with the useful idioms that everyone else uses to see how much I still have to learn. (-: -- Mark ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe