From 3b6f0d4c7d3bd2a53469c5b0484908f42d9c066f Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sun, 18 Feb 2018 04:46:38 +0300 Subject: peculiar: move to _posts/ --- _drafts/peculiar_indentation.md | 107 ------------------------------ _posts/2018-02-18-peculiar-indentation.md | 107 ++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 107 deletions(-) delete mode 100644 _drafts/peculiar_indentation.md create mode 100644 _posts/2018-02-18-peculiar-indentation.md diff --git a/_drafts/peculiar_indentation.md b/_drafts/peculiar_indentation.md deleted file mode 100644 index 9c6930d..0000000 --- a/_drafts/peculiar_indentation.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Peculiar Haskell indentation -layout: post -excerpt: > - An explanation of how Haskell indentation works inside 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) -``` diff --git a/_posts/2018-02-18-peculiar-indentation.md b/_posts/2018-02-18-peculiar-indentation.md new file mode 100644 index 0000000..9c6930d --- /dev/null +++ b/_posts/2018-02-18-peculiar-indentation.md @@ -0,0 +1,107 @@ +--- +title: Peculiar Haskell indentation +layout: post +excerpt: > + An explanation of how Haskell indentation works inside 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) +``` -- cgit v1.2.3