缩进的import语句导致style -haskell解析错误



当尝试格式化以下测试程序Char.hs时,style -haskell报告解析错误:

module Char (caesarCipher, caesarDecipher)
where
import Data.Char (ord, chr)
caesarCipher :: Int -> [Char] -> [Char]
caesarCipher shift msg = map (chr) $ map (+ shift) $ map (ord) msg
caesarDecipher :: Int -> [Char] -> [Char]
caesarDecipher shift msg = map (chr) $ map (subtract shift) $ map (ord) msg

style -haskell:

详细日志的一部分
$ stylish-haskell -v Char.hs          
...
Stylish Haskell will work basing on LANGUAGE pragmas in source files.
Enabled Cases step
Enabled Imports (ghc-lib-parser) step
Enabled LanguagePragmas step
Enabled TrailingWhitespace step
Extra language extensions: []
Char.hs: <string>:6:5: error: parse error on input `caesarCipher'

style -haskell没有配置任何配置文件,如详细报告的折叠部分所示;Char.hs是一个独立的非项目文件,GHC在编译过程中没有任何抱怨:

$ ghc Char.hs   
[1 of 1] Compiling Char             ( Char.hs, Char.o )

经过一些测试后,问题似乎是关于import语句,其中:

  • style -haskell删除所有缩进后工作良好:

    module Char (caesarCipher, caesarDecipher)
    where
    import Data.Char (ord, chr)
    caesarCipher :: Int -> [Char] -> [Char]
    caesarCipher shift msg = map (chr) $ map (+ shift) $ map (ord) msg
    caesarDecipher :: Int -> [Char] -> [Char]
    caesarDecipher shift msg = map (chr) $ map (subtract shift) $ map (ord) msg
    
  • style -haskell也只在删除import语句时工作,即使GHC抱怨这个:

    module Char (caesarCipher, caesarDecipher)
    where
    -- import Data.Char (chr, ord)
    caesarCipher :: Int -> [Char] -> [Char]
    caesarCipher shift msg = map (chr) $ map (+ shift) $ map (ord) msg
    caesarDecipher :: Int -> [Char] -> [Char]
    caesarDecipher shift msg = map (chr) $ map (subtract shift) $ map (ord) msg
    

唯一让style -haskell不高兴的似乎是缩进的import语句。澄清一下,我知道import语句必须与其他语句在相同的缩进级别上,我在任何情况下都没有违反这一点;我一直在使用空格字符而不是制表符,我从来没有在任何情况下混合使用它们。


所以我的问题是:

  • 是否在语法上接受缩进整个模块体一个额外的水平向前?我没有看到很多这样做的代码示例,但也没有一些文章说"不要这样做">
  • 如果是,那么是什么导致style -haskell不工作,而代码是语法正确的?
  • 如果没有,为什么GHC什么都没说?
  • 有可能保持缩进,而使style -haskell工作吗?

谁可能感兴趣,我使用GHC 8.10.7和style -haskell 0.14.1.0。如果你需要更多的信息就喊我。

Haskell的缩进规则在Haskell报告的10.3节中有正式的规定,在2.7节中给出了简化的版本。

我的理解如下(在您的程序中)。

  1. 程序体是一个导入和顶级声明的列表。
  2. 当使用布局规则时,所有这些必须有相同的缩进。
  3. 缩进的级别由wherefrom模块后的第一个声明决定。

基于此,上述所有程序都应该是正确的。

指出:

  1. 身体是module ...... where之后的一切
  2. 使用布局规则的另一种选择是手动添加大括号{,}和分号;来分隔声明,类似于在c语言中是如何完成的。这会给你一个'布局不敏感的程序'
  3. Haskell语法的实际定义使用大括号和分号。该规范描述了如何将文件的布局转换为布局不敏感的。关于该算法的完整描述,请再次参阅1,关于实际的Haskell语法定义,请参阅下面的10.5节。

最新更新