aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/_posts/2018-02-18-peculiar-indentation.md
diff options
context:
space:
mode:
Diffstat (limited to '_posts/2018-02-18-peculiar-indentation.md')
-rw-r--r--_posts/2018-02-18-peculiar-indentation.md106
1 files changed, 0 insertions, 106 deletions
diff --git a/_posts/2018-02-18-peculiar-indentation.md b/_posts/2018-02-18-peculiar-indentation.md
deleted file mode 100644
index 7832194..0000000
--- a/_posts/2018-02-18-peculiar-indentation.md
+++ /dev/null
@@ -1,106 +0,0 @@
----
-title: Peculiar Haskell indentation
-excerpt: >
- An explanation for nasty `parse error`s I used to get for nested `do`
- blocks.
-category: Haskell
-custom_css:
- - syntax.css
----
-I've fallen into a Haskell indentation pitfall.
-I think it must be common, so I'm describing it here.
-
-The problem is that indentation rules in `do` blocks are not intuitive to me.
-For example, the following function is valid Haskell syntax:
-
-```haskell
-foo1 :: IO ()
-foo1 =
- alloca $ \a ->
- alloca $ \b ->
- alloca $ \c -> do
- poke a (1 :: Int)
- poke b (1 :: Int)
- poke c (1 :: Int)
- return ()
-```
-
-In fact, this funnier version is also OK:
-
-```haskell
-foo2 :: IO ()
-foo2 = alloca $ \a ->
- alloca $ \b ->
- alloca $ \c -> do
- poke a (1 :: Int)
- poke b (1 :: Int)
- poke c (1 :: Int)
- return ()
-```
-
-If you add an outer `do` however, things become a little more complicated.
-For example, this is the valid version of the functions above with an outer
-`do`:
-
-```haskell
-foo3 :: IO ()
-foo3 = do
- alloca $ \a ->
- alloca $ \b ->
- alloca $ \c -> do
- poke a (1 :: Int)
- poke b (1 :: Int)
- poke c (1 :: Int)
- return ()
-```
-
-Notice the extra indentation for each of the `alloca`s.
-When I tried to remove these seemingly excessive indents, GHC complained with
-the usual `parse error (possibly incorrect indentation or mismatched
-brackets)`.
-
-```haskell
-foo4 :: IO ()
-foo4 = do
- alloca $ \a ->
- alloca $ \b ->
- alloca $ \c -> do
- poke a (1 :: Int)
- poke b (1 :: Int)
- poke c (1 :: Int)
- return ()
-```
-
-The truth is, the rules for desugaring `do` blocks are surprisingly simple and
-literal.
-GHC inserts semicolons according to the rules [found in the Wikibook].
-So it inserts semicolons between the `alloca`s on the same level, so `foo4`
-becomes:
-
-```haskell
-foo4 :: IO ()
-foo4 = do
- { alloca $ \a ->
- ; alloca $ \b ->
- ; alloca $ \c -> do
- { poke a (1 :: Int)
- ; poke b (1 :: Int)
- ; poke c (1 :: Int)
- ; return ()
- }
- }
-```
-
-[found in the Wikibook]: https://en.wikibooks.org/wiki/Haskell/Indentation#Explicit_characters_in_place_of_indentation
-
-The semicolons after `->` are clearly invalid Haskell syntax, hence the error.
-
-P.S. To compile the functions above, you need to include them in a module and
-add proper imports, e.g.
-
-```haskell
-module PeculiarIndentation where
-
-import Foreign.Marshal.Alloc (alloca)
-import Foreign.Storable (poke)
-```