
Proposal: add a non-recursive let to the Haskell language. In let' p = e in e' do { ... let' p = e ... } the variables of pattern p are then *not* in scope in e. Reasons for adding a non-recursive let: 1. recursive-let is the source for many non-termination bugs. An instance of such a bug is in the state monad of mtl-2.1 (forgive me, Edward, for quoting this again): http://hackage.haskell.org/packages/archive/mtl/2.1/doc/html/src/Control-Mon... state :: (s -> (a, s)) -> m a state f = do s <- get let ~(a, s) = f s put s return a here, a non-recursive let was meant, the s bound by the let was supposed to be a new state, shadowing the old state. However, since let is recursive, this actually causes a loop. Another instance (cut-down) are let-guards like let Just x | x > 0 = e in x The "x > 0" is understood as an assertion here, documenting an invariant. However, Haskell reads this as let Just x = case () of { () | x > 0 -> e } in x leading to non-termination. A non-recursive version let' Just x | x > 0 = e in x could be interpreted as case e of { Just x | x > 0 -> x } instead, which is meaningful (in contrast to the current interpretation). 2. Connected to 1., a non-recursive let allows for painless shadowing. For instance, the hack do ... x <- return $ f x exploiting non-recursiveness of the <- binding, would be unnecessary, instead we could write do ... let' x = f x NB: In a do-Block, we could drop the keyword let' and simply write do ... x = f x for a non-monadic binding, in accordance to x <- mf x, See also http://www.haskell.org/pipermail/beginners/2009-February/001075.html http://stackoverflow.com/questions/8398607/declaration-order-in-let-bindings... PS.: I can work out the details of grammar and semantics if this proposal finds followers. Cheers, Andreas -- Andreas Abel <>< Du bist der geliebte Mensch. Theoretical Computer Science, University of Munich Oettingenstr. 67, D-80538 Munich, GERMANY andreas.abel@ifi.lmu.de http://www2.tcs.ifi.lmu.de/~abel/