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)
i am getting this compilation error
The last statement in a ‘do’ construct must be an expression:
let intermediatebs = unfoldrN ((B.length bs) * 2) unfld 0
It’s hard to see exactly what you want here. It is possible to make your code parse with only indentation changes:
although it won’t compile due to ambiguous
getLineandputStrLnoccurrences. You may want toimport qualifiedwhere appropriate. Key observations:Do-blocks, let-blocks etc. start from the left edge of the first thing inside them, regardless of where the keyword is itself. E.g.
As a consequence, I often give
doandwheretheir own line before starting a block. In the example I gave above, you can see that even if I moved the do-block into a function with a longer or shorter name, the indentation wouldn’t change.Lines in the same block that start indented are a continuation of the previous line. Guards are a continuation so need to be indented, likewise
wherefor a let assignment needs to be indented further than the assignment itself.in doat the end of your block was redundant, so I removed it (alternatively, just indenting it would have worked too).