2012-10-27 15 views
3
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) 

我得到這個編譯錯誤 最後一條語句在「做」結構必須是一個表達式: 讓intermediatebs = unfoldrN((B.length bs)* 2)unfld 0在「做」結構的最後一條語句必須是一個表達式:有沒有壓痕錯誤

+0

看起來你有三個'let'但只有一個'in'。這不會很好結束。那麼'let'和'where'綁定的混合是什麼? –

+0

@HenningMakholm頭兩個'let's在'do'-block內,不需要'in'。 – sepp2k

+1

這裏的主要問題是(a)縮進錯誤(b)使用哪裏可能會更清楚,但主要和最明顯(c)試圖在一個主要內容中做所有事情。它很難調試。請把你的代碼重新編寫成單獨的函數,直到你可以寫出main = fmap myProcessingFunction getLine >> = putStrLn – AndrewC

回答

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 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塊移到了名稱較長或較短的函數中,縮進也不會改變。

  • 開始縮進的同一塊中的行是前一行的延續。後衛是需要縮進的延續,同樣where對於賦值任務需要比賦值本身進一步縮進。

  • 在塊的末尾是多餘的,所以我刪除它(或者,縮進它也可以)。
1

錯誤消息不是由縮進錯誤引起的,而是由於排序錯誤造成的。您似乎已將where - 區塊插入do區塊的中間。這是行不通的。整個do - 塊,包括最終表達式,應該在where塊之前。

也就是說,您的where -block內的定義中確實存在縮進錯誤:您需要縮進模式守衛。

+0

確實,它不容易看到OP在這裏的內容。假定where子句包括convertASCIIword在內的所有內容,但爲什麼當後續文本具有相同的indendation時,編譯器應該停止在那裏。但是如果最後一個包含在哪裏,那麼外層do的最後一行確實是let,這是一個錯誤。 – Ingo

1

你的外do只包含自以下令牌letinput <- getLine已經低於input indended(這是沒有意義的,無論如何,但是......)

也許你的意思是:

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

但人們只能猜測。使用indendation來明確哪些項目屬於一起,哪些項目是他人的子項目。上面的風格比較模糊了這一點。此外,你不應該寫

foo x y z 
| ..... = 

,因爲編譯器會看到

foo x y z; | ... = 
相關問題