Closed Izaakwltn closed 4 months ago
I don't think this is a "bug", but it's something we could opt to support.
DO syntax has relatively tight allowance for what's allowed, and same for LET syntax. LET syntax itself doesn't allow fragments of DO to be used within its syntax.
I consider this a bug. Do should support the full expression syntax.
How much syntax? Is this OK?
(do
(x <- (fn () (y <- ...))
...)
I don't believe Haskell supports what you're suggesting. let
in a Haskell do
is statement syntax of the do
itself, which gets desugared to a normal let
expression. See this BNF-ish grammar here. The relevant part:
exp -> ...
| do { stmts } (do expression)
...
stmts -> stmt1 ... stmtn exp [;] (n>=0)
stmt -> exp ;
| pat <- exp ;
| let decls ;
| ; (empty statement)
Same thing with Rust's do_notation
crate.
For these reasons I don't agree.
How much syntax? Is this OK?
no
See this BNF-ish grammar here. The relevant part:
From the grammar it looks like all expressions are valid statements. The following compiles on ghc 9.6.4:
main = do
let x = "hello" in putStrLn x
putStrLn "world"
@eliaslfox I might have read into your suggestion too much, thinking you were saying statements should be allowed anywhere within expressions (which is the last example of this issue).
I agree then that expressions should be allowed, but statements (as they're called in the grammar) should only be in the syntax of do.
Apologies for the misunderstanding.
No worries. I missed that detail when reading the last example.
The following compiles in Coalton currently:
COALTON-USER> (coalton-toplevel
(define (f x)
(do
(y <- (pure x))
(let ((z y))
(pure z)))))
; No value
COALTON-USER> (type-of 'f)
∀ :A :B. MONAD :B ⇒ (:A → (:B :A))
It looks like the correct behavior is implemented.
Here's an example:
Without let:
It also works with a standalone, non-wrapped let:
However it doesn't compile with a wrapped let:
Compiling
add-to-state-twice3
returns the error: