Question about scope of 'let' and 'where'
In the function body (rhs): let { a = (e1) } in (e2) where { b = f a } Does the Haskell specification indicate that the definition of 'a' is in-scope for the definition of 'b'? Practical experience using HUGS suggests the answer is no, but my intuition is that the answer should be yes. I was unable to find anything in either the report or the "gentle introduction" that made the correct answer clear to me (which is not to say it's not there, just that I didn't find it). I think the tutorial might benefit from a discussion of what is in-scope for where clauses. <comment> FWIW, my intuition was that e where defs was a form of expression (like let ... in), in which some sub-expressions were factored out as subsidiary definitions; i.e. that I'd expect to be able to replace each occurrence of a name defined by 'where' with the body of the corresponding definition. Hence I'd expect the let definitions to be in-scope. I now see that use of 'where' is restricted to specific contexts. I wonder if such restriction is needed? The differences between let and where in Haskell are something I find to be confusing. </comment> #g ------------------- Graham Klyne <GK@NineByNine.org> PGP: 0FAA 69FF C083 000B A2E9 A131 01B9 1C7A DBCA CB5E
It is not. Lets are expressions. Wheres are part of declarations. In a grammar sense, you have something like: funcdef ::= name = expr (where decls)? expr ::= let decls in expr so the declarations inside a let are internal to the expression and can't go outside into the where clause. -- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume On Sun, 16 Mar 2003, Graham Klyne wrote:
In the function body (rhs):
let { a = (e1) } in (e2) where { b = f a }
Does the Haskell specification indicate that the definition of 'a' is in-scope for the definition of 'b'?
Practical experience using HUGS suggests the answer is no, but my intuition is that the answer should be yes.
I was unable to find anything in either the report or the "gentle introduction" that made the correct answer clear to me (which is not to say it's not there, just that I didn't find it). I think the tutorial might benefit from a discussion of what is in-scope for where clauses.
<comment> FWIW, my intuition was that
e where defs
was a form of expression (like let ... in), in which some sub-expressions were factored out as subsidiary definitions; i.e. that I'd expect to be able to replace each occurrence of a name defined by 'where' with the body of the corresponding definition. Hence I'd expect the let definitions to be in-scope.
I now see that use of 'where' is restricted to specific contexts. I wonder if such restriction is needed? The differences between let and where in Haskell are something I find to be confusing. </comment>
#g
------------------- Graham Klyne <GK@NineByNine.org> PGP: 0FAA 69FF C083 000B A2E9 A131 01B9 1C7A DBCA CB5E
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
[Hal Daume III <hdaume@ISI.EDU>]
It is not. Lets are expressions. Wheres are part of declarations. In a grammar sense, you have something like:
funcdef ::= name = expr (where decls)? expr ::= let decls in expr
so the declarations inside a let are internal to the expression and can't go outside into the where clause.
Shouldn't the layout rule make this apparent? Is the following really OK?
In the function body (rhs):
let { a = (e1) } in (e2) where { b = f a }
I'd say that's pretty misleading, and maybe should be illegal layout...? Matt -- Matt Hellige matt@immute.net http://matt.immute.net
No, that's not legal. You'll get an unbound variable error on the use of 'a' in the definition of 'b'. This doesn't really have anything to do with layout. Consider the following definition:
f x = case x of Nothing -> ... Just (y,z) -> let Just q = z in b where b = g q
does it really make sense to let the where clause look that deep into an expression to pull out a variable? And what if you use the name 'q' multiple times in the expression? -- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume On Mon, 17 Mar 2003, Matt Hellige wrote:
[Hal Daume III <hdaume@ISI.EDU>]
It is not. Lets are expressions. Wheres are part of declarations. In a grammar sense, you have something like:
funcdef ::= name = expr (where decls)? expr ::= let decls in expr
so the declarations inside a let are internal to the expression and can't go outside into the where clause.
Shouldn't the layout rule make this apparent? Is the following really OK?
In the function body (rhs):
let { a = (e1) } in (e2) where { b = f a }
I'd say that's pretty misleading, and maybe should be illegal layout...?
Matt
-- Matt Hellige matt@immute.net http://matt.immute.net _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
[Hal Daume III <hdaume@ISI.EDU>]
No, that's not legal. You'll get an unbound variable error on the use of 'a' in the definition of 'b'. This doesn't really have anything to do with layout. Consider the following definition:
f x = case x of Nothing -> ... Just (y,z) -> let Just q = z in b where b = g q
does it really make sense to let the where clause look that deep into an expression to pull out a variable? And what if you use the name 'q' multiple times in the expression?
Right, I understand that it's an illegal 'where' clause. That was the point of the original post... I chose a bad example by using the example from the original question, which we've already established as illegal. My question has to do only with layout... Consider: f x = let ... in ... where ... Assuming that all the ...s are legal, is this OK? Should it be? It really makes the 'where' clause look like it's inside the 'let', when in fact it can't be. Sorry about the misunderstanding and lousy example... Matt -- Matt Hellige matt@immute.net http://matt.immute.net
Hi,
f x = let ... in ... where ...
Assuming that all the ...s are legal, is this OK? Should it be? It really makes the 'where' clause look like it's inside the 'let', when in fact it can't be.
Ah, sorry. Yes, this is legal. However, if you think about 'where's attaching to declarations, not expressions, I don't think you get too confused about it being indented "too much." Again, this is because the where clause (include its layout rules) doesn't care at all what your function body expression looks like. Personally, I don't often mix top-level lets and wheres, unless I have a good reason to do so. Though not for this reason, it does clean this up.
At 22:00 16/03/2003 -0800, Hal Daume III wrote:
It is not. Lets are expressions. Wheres are part of declarations. In a grammar sense, you have something like:
funcdef ::= name = expr (where decls)? expr ::= let decls in expr
so the declarations inside a let are internal to the expression and can't go outside into the where clause.
I see now. Thanks. #g ------------------- Graham Klyne <GK@NineByNine.org> PGP: 0FAA 69FF C083 000B A2E9 A131 01B9 1C7A DBCA CB5E
Graham Klyne writes: | In the function body (rhs): | | let | { a = (e1) } | in | (e2) | where | { b = f a } : | <comment> : | I now see that use of 'where' is restricted to specific contexts. I wonder | if such restriction is needed? The differences between let and where in | Haskell are something I find to be confusing. | </comment> Hi. Other people have already replied confirming *that* the 'where' has a broader scope than the 'let' in the rhs of a function. Here's an example of *why* the broad 'where' scope can be useful: it allows us to share definitions between a function body and its guard, and among multiple guarded branches. The following is from Hugs's Prelude, and shows definitions being shared by two branches. floatProperFraction x | n >= 0 = (fromInteger m * fromInteger b ^ n, 0) | otherwise = (fromInteger w, encodeFloat r n) where (m,n) = decodeFloat x b = floatRadix x (w,r) = quotRem m (b^(-n)) HTH. Tom
participants (4)
-
Graham Klyne -
Hal Daume III -
Matt Hellige -
Tom Pledger