'do'结构中的最后一个语句必须是一个表达式:是否有任何缩进错误

时间:2012-10-27 16:35:56

标签: haskell

import Data.ByteString as B
import Data.ByteString.Internal as I
import Data.Bits
main = do input <- getLine
      let bs = B.pack input
      let intermediatebs  =  unfoldrN ((B.length bs)*2) unfld 0
      where unfld i
      |Prelude.rem i 2 == 0 = Just (top4 $ B.index bs (i/2) , i+1)
      |otherwise =  Just (bottom4 $ B.index bs (i/2) , i+1)
      top4bits x = shiftR x 4
      bottom4bits x = x .&. 0x0F
      top4 x = convertASCIIword8 $ top4bits x
      bottom4 x = convertASCIIword8 $ bottom4bits x
      convertASCIIword8 x
      |x <= 9 = I.c2w '0' + x
      |otherwise = I.c2w 'A' + (x-10)
      let outputbs = B.map I.w2c $ intermediatebs
      in do putStrLn (outputbs)

我收到此编译错误 'do'结构中的最后一个语句必须是一个表达式:     let intermediatebs = unfoldrN((B.length bs)* 2)unfld 0

3 个答案:

答案 0 :(得分:5)

很难在这里看到你想要的东西。只有缩进更改才可以解析代码:

import Data.ByteString as B
import Data.ByteString.Internal as I
import Data.Bits
main = do
  input <- getLine
  let bs = B.pack input
  let intermediatebs  =  unfoldrN ((B.length bs)*2) unfld 0
       where
        unfld i
          | Prelude.rem i 2 == 0 = Just (top4 $ B.index bs (i/2) , i+1)
          | otherwise =  Just (bottom4 $ B.index bs (i/2) , i+1)
        top4bits x = shiftR x 4
        bottom4bits x = x .&. 0x0F
        top4 x = convertASCIIword8 $ top4bits x
        bottom4 x = convertASCIIword8 $ bottom4bits x
        convertASCIIword8 x
          | x <= 9 = I.c2w '0' + x
          | otherwise = I.c2w 'A' + (x-10)
  let outputbs = B.map I.w2c $ intermediatebs
  putStrLn (outputbs)

虽然由于getLineputStrLn出现不明确而无法编译。您可能需要import qualified。主要观察:

  • 无论关键字本身在哪里,Do-blocks,let-blocks等都从内部的第一个内容开始。 E.g。

    do x
       y
    -- ^ because of where the x is, all future lines have to line up with it
    
    let x = ...
        y = ...
    -- ^ if you have code appearing left of here, the let-block ends
    

    因此,我经常在开始阻止之前给dowhere他们自己的行。在上面给出的示例中,您可以看到即使我将do-block移动到名称更长或更短的函数中,缩进也不会改变。

  • 开始缩进的同一块中的行是前一行的延续。防护是一个延续,因此需要缩进,同样where的let赋值需要比赋值本身缩进。

  • 你方块末尾的in do是多余的,所以我删除了它(或者,只是缩进它也会有用)。

答案 1 :(得分:1)

错误消息不是由缩进错误引起的,而是由于排序错误引起的。您似乎已在where - 块的中间插入do - 块。这不起作用。整个do - 块,包括最终表达式,应该在where块之前。

也就是说,你的where块内的定义中有缩进错误:你需要缩进模式保护。

答案 2 :(得分:1)

您的外部do仅由input <- getLine组成,因为以下令牌let的入口次数已经低于input(这无论如何都没有意义,但......)

也许你的意思是:

do  input <- getLine
    let ....
    let .....   where 
          unfld ....

但人们只能猜测。使用indendation来明确哪些项目属于一起,以及哪些项目是其他项目的子项目。上面的风格相当模糊了这一点。另外,你不应该写

foo x y z
| ..... = 

因为编译器会看到

foo x y z; | ... =