Haskell 要求分号换行

问题描述 投票:0回答:1

我是 Haskell 新手,有一个大学作业任务,只编译 一行仅由一个分号组成。我很好奇,这是否是有意的行为,如果是,为什么?

(过去几天我编写了一些有趣的代码行,但没有按预期工作,每个代码行都是一个小讲座,例如

--|
不是注释掉的守卫,而是未定义的运算符等)

我工作的唯一版本是(完整代码如下):

   case input of {
       ... -- some other code
       ('0':xs)     -> [(next Zero, rest)] where (next, rest) = readAll xs
       ;
       ... -- some other code
   }

我想知道是否可以在没有由单个分号组成的行的情况下完成此操作,以及为什么下面的示例不起作用。

我尝试过,例如

       ('0':xs)     -> [(next Zero, rest)] where (next, rest) = readAll xs;
       ('0':xs)     -> [(next Zero, rest)] where (next, rest) = (readAll xs);
       ('0':xs)     -> [(next Zero, rest)]
          where
             (next, rest) = (readAll xs);

但它们都导致了同样的错误:

file.hs:19:8: error: parse error on input ‘(’
   |
19 |        ('1':xs)     -> [(next One , rest)] where (next, rest) = readAll xs
   |        ^

可运行的代码片段:

data BinaryDigit = Zero | One
data BinaryNumber = L BinaryDigit -- L: last digit
                  | E BinaryDigit BinaryNumber -- E: intermediate digit

instance Show BinaryNumber where
   show (L Zero) = "0"
   show (L One ) = "1"
   show (E digit next) = show (L digit) ++ show next

instance Read BinaryNumber where
     -- idea:
     --   next item must be known to decide whether E or L constructor to use
     --   create function that will be called on the next element and returns the right constructor,
     --   with only one parameter, the current digit value, unset
   readsPrec _ input = case input of {
       ('0':'0':xs) -> readsPrec 0 ('0':xs);
       ('0':'1':xs) -> readsPrec 0 ('1':xs);
       ('0':xs)     -> [(next Zero, rest)] where (next, rest) = readAll xs
       ;
       ('1':xs)     -> [(next One , rest)] where (next, rest) = readAll xs
       ;
       otherwise    -> [];
   } where
     readAll :: String -> (BinaryDigit -> BinaryNumber, String)
     readAll ('0':xs) = ((`E` (next Zero)), rest) where (next, rest) = readAll xs
     readAll ('1':xs) = ((`E` (next One )), rest) where (next, rest) = readAll xs
     readAll str      = (L, str)

main = putStrLn $ show (read "110" :: BinaryNumber)
haskell syntax
1个回答
1
投票

您需要分号的原因是您通过在第 15 行和第 23 行使用大括号禁用了 case 表达式的

layout
,因此必须用分号明确分隔各个选项。

如果您在

where
子句中声明的表达式之一后添加分号,则该分号将被解释为分隔该
where
子句中声明的表达式。因此分号必须位于
where
的布局块之外。一种解决方案是将
where
子句本身括在大括号中:

   readsPrec _ input = case input of {
       ('0':'0':xs) -> readsPrec 0 ('0':xs);
       ('0':'1':xs) -> readsPrec 0 ('1':xs);
       ('0':xs)     -> [(next Zero, rest)] where {(next, rest) = readAll xs};
       ('1':xs)     -> [(next One , rest)] where {(next, rest) = readAll xs};
       otherwise    -> [];
   } where

但是惯用的 Haskell 会利用布局并避免任何分号:

   readsPrec _ input = case input of
       ('0':'0':xs) -> readsPrec 0 ('0':xs)
       ('0':'1':xs) -> readsPrec 0 ('1':xs)
       ('0':xs)     -> [(next Zero, rest)] where (next, rest) = readAll xs
       ('1':xs)     -> [(next One , rest)] where (next, rest) = readAll xs
       otherwise    -> []
     where
© www.soinside.com 2019 - 2024. All rights reserved.