
Hello Terry On Sun, Jul 07, 2019 at 11:24:47AM -0400, Terry Phelps wrote:
I found this code on the net somewhere. It compiles and works properly:
import qualified Data.ByteString as BS import Text.Printf (printf) toHex :: BS.ByteString -> String toHex bytes = do hex <- BS.unpack bytes printf "%02x" hex
I cannot understand the 'do' notation is required, because it seems to be a pure function. I guess there's a monad hiding somewhere that my newbie mind can't see.
`toHex` is pure (non IO), but it has an /effect/. In this case, it takes advantage of the list monad to achieve non-determinism. Specifically, since unpack :: ByteString -> [Word8] printf (which in our case has signature (`String -> Char`) gets called on each of those [Word8]. The result will obviously be [Char], which `String` is an alias of.
So, I rewrote the code to remove the 'do stuff':
[...] toHex :: BS.ByteString -> String toHex bytes = printf "02x" (BS.unpack bytes)
A do-less version still is /monadic/, hence it will have >>= or >> or similar somewhere. This works: toHex2 :: BS.ByteString -> String toHex2 bytes = BS.unpack bytes >>= printf "%02x" and follows the reasoning above (feed every every Word8 to `printf "%02x"`). Does this answer your questions? -F