In Haskell, why do you not use 'in' with 'let' inside of a do-block, but you must otherwise?
For example, in the somewhat contrived examples below:
afunc :: Int -> Int
afunc a =
let x = 9 in
a * x
amfunc :: IO Int -> IO Int
amfunc a = do
let x = 9
a' <- a
return (a' * x)
It's an easy enough rule to remember, but I just don't understand the reason for it.
Keywords are the words and phrases that people type into search engines to find what they're looking for. For example, if you were looking to buy a new jacket, you might type something like “mens leather jacket” into Google. Even though that phrase consists of more than one word, it's still a keyword.
A keyword is a term used in digital marketing to describe a word or a group of words an Internet user uses to perform a search in a search engine or search bar. In an SEO strategy, keywords are very important and should be the core of any copy written for the web (present in the content, titles and SEO elements).
Keywords are words or phrases that users type into search engines to find relevant content for their queries. Because keywords come from search queries, incorporating these terms into your content strategy helps search engines rank your website pages and users find your content when looking for it.
When researching to discover a user's intentions behind making a search, we can classify all keywords into four main categories of intent: commercial, transactional, informational, and navigational. We're going to identify what these types are with a short breakdown of each type.
You are providing expressions to define both afunc
and amfunc
. Let-expressions and do-blocks are both expressions. However, while a let-expression introduces a new binding that scopes around the expression given after the 'in' keyword, a do-block isn't made of expressions: it is a sequence of statements. There are three forms of statements in a do-block:
a computation whose result is bound to some variable x
, as in
x <- getChar
a computation whose result is ignored, as in
putStrLn "hello"
A let-statement, as in
let x = 3 + 5
A let-statement introduces a new binding, just as let-expressions do. The scope of this new binding extends over all the remaining statements in the do-block.
In short, what comes after the 'in' in a let-expression is an expression, whereas what comes after a let expression is a sequence of statements. I can of course express a computation of a particular statement using a let-expression, but then the scope of the binding would not extend beyond that statement to statements that follow. Consider:
do putStrLn "hello"
let x = 3 + 5 in putStrLn "eight"
putStrLn (show x)
The above code causes the following error message in GHC:
Not in scope: `x'
whereas
do putStrLn "hello"
let x = 3 + 5
putStrLn "eight"
putStrLn (show x)
works fine.
You can indeed use let .. in
in do-notation. In fact, according to the Haskell Report, the following
do{let decls; stmts}
desugars into
let decls in do {stmts}
I imagine that it is useful because you might otherwise have to have some deep indentation or delimiting of the "in"-block, going from your in .. to the very end of the do-block.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With