Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do `do` and `where` mix?

Tags:

haskell

From some book I have the following code snippets

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int)
mutableUpdateIO n = do
  mvec <- GM.new (n + 1)
  go n mvec
  where
    go 0 v = return v
    go n v = (MV.write v n 0) >> go (n - 1) v

mutableUpdateST :: Int -> V.Vector Int
mutableUpdateST n =
  runST $ do
    mvec <- GM.new (n + 1)
    go n mvec
  where
    go 0 v = V.freeze v
    go n v = (MV.write v n 0) >> go (n - 1) v

like hindent indents them. Now I want to introduce all braces and semicolons, so the whitespace isn't relevant any more. Just because I am curious.

The second example suggests, that the where belongs to the whole runST $ do ... expression, but the first example suggests, that the where is somehow a part of the go n mvec statement. Reading in Haskell Report Chapter 2.7 I tried to introduce braces and semicolons in the first example like

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int)
mutableUpdateIO n = do {
  mvec <- GM.new (n + 1);
  go n mvec;
  where {
    go 0 v = return v;
    go n v = (MV.write v n 0) >> go (n - 1) v;
  } ; }

But I get a parsing error. Why is that?

Why is the layout hindent produces for the first example mutableUpdateIO valid Haskell? Shouldn't the braces and semicolons be introduced like in my above try?

like image 692
typetetris Avatar asked Jul 25 '17 14:07

typetetris


People also ask

What is the 1db rule?

Rule 9: A 1 dB change in loudness is a just noticeable difference (JND). At mid loudness levels, a 1-dB change in loudness is just noticeable. A 1-dB increase requires a 25% increase in power. At higher loudnesses, changes as small as 1/3 dB may be noticeable.


1 Answers

The where blocks belong neither to the runST $ do ... expression nor to the go n mvec statement; they belong to the mutableUpdateIO n = ... declaration and the mutableUpdateST n = ... declaration. The braces and semicolons should go like this:

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int)
mutableUpdateIO n = do {
  mvec <- GM.new (n + 1);
  go n mvec;
  } where {
    go 0 v = return v;
    go n v = (MV.write v n 0) >> go (n - 1) v;
  }

The relevant sentence from the informal description in the Report in chapter 2.7 is this:

A close brace is also inserted whenever the syntactic category containing the layout list ends; that is, if an illegal lexeme is encountered at a point where a close brace would be legal, a close brace is inserted.

Since where is an illegal lexeme inside an expression, this ends the do block and a close brace is inserted there. This also explains why the layout hindent produced was legal.

like image 177
Daniel Wagner Avatar answered Nov 11 '22 21:11

Daniel Wagner