<div dir="ltr"><br clear="all"><div>I'm continuing my now-and-then exploration of Haskell.</div><div><br></div><div>I'm getting a new crop of type errors that I'm pulling my hair out over.</div><div><br></div><div>The errors I'm getting are:</div><div><br></div><div><div>$ make</div><div>below cmd output started 2015 Tue Dec 01 04:05:17 PM PST</div><div># --make will go out and find what to build</div><div>ghc -Wall --make -o dph dph.hs Split0.hs</div><div>[1 of 3] Compiling Split0           ( Split0.hs, Split0.o )</div><div>[2 of 3] Compiling Md5s             ( Md5s.hs, Md5s.o )</div><div>[3 of 3] Compiling Main             ( dph.hs, dph.o )</div><div><br></div><div>dph.hs:13:13:</div><div>    Couldn't match type `IO' with `(,) (IO String)'</div><div>    Expected type: (IO String, String)</div><div>      Actual type: IO String</div><div>    In a stmt of a 'do' block: hash <- prefix_md5 filename :: IO String</div><div>    In the expression:</div><div>      do { hash <- prefix_md5 filename :: IO String;</div><div>           (hash, filename) }</div><div>    In an equation for `do_prefix_hash':</div><div>        do_prefix_hash filename</div><div>          = do { hash <- prefix_md5 filename :: IO String;</div><div>                 (hash, filename) }</div><div><br></div><div>dph.hs:14:6:</div><div>    Couldn't match type `[Char]' with `IO String'</div><div>    Expected type: IO String</div><div>      Actual type: String</div><div>    In the expression: hash</div><div>    In a stmt of a 'do' block: (hash, filename)</div><div>    In the expression:</div><div>      do { hash <- prefix_md5 filename :: IO String;</div><div>           (hash, filename) }</div><div><br></div><div>dph.hs:24:23:</div><div>    Couldn't match type `[]' with `IO'</div><div>    Expected type: IO (IO String, String)</div><div>      Actual type: [(IO String, String)]</div><div>    In a stmt of a 'do' block:</div><div>      io_hash_tuples <- map do_prefix_hash filenames ::</div><div>                          [(IO String, String)]</div><div>    In the expression:</div><div>      do { buffer <- (hGetContents stdin) :: IO String;</div><div>           let filenames = ...;</div><div>           io_hash_tuples <- map do_prefix_hash filenames ::</div><div>                               [(IO String, String)];</div><div>           hash_tuples <- sequence io_hash_tuples :: [(String, String)];</div><div>           .... }</div><div>    In an equation for `main':</div><div>        main</div><div>          = do { buffer <- (hGetContents stdin) :: IO String;</div><div>                 let filenames = ...;</div><div>                 io_hash_tuples <- map do_prefix_hash filenames ::</div><div>                                     [(IO String, String)];</div><div>                 .... }</div><div><br></div><div>dph.hs:25:20:</div><div>    Couldn't match type `[a0]' with `(String, String)'</div><div>    Expected type: [(String, String)]</div><div>      Actual type: [[a0]]</div><div>    In the return type of a call of `sequence'</div><div>    In a stmt of a 'do' block:</div><div>      hash_tuples <- sequence io_hash_tuples :: [(String, String)]</div><div>    In the expression:</div><div>      do { buffer <- (hGetContents stdin) :: IO String;</div><div>           let filenames = ...;</div><div>           io_hash_tuples <- map do_prefix_hash filenames ::</div><div>                               [(IO String, String)];</div><div>           hash_tuples <- sequence io_hash_tuples :: [(String, String)];</div><div>           .... }</div><div><br></div><div>dph.hs:25:20:</div><div>    Couldn't match type `[]' with `IO'</div><div>    Expected type: IO (String, String)</div><div>      Actual type: [(String, String)]</div><div>    In a stmt of a 'do' block:</div><div>      hash_tuples <- sequence io_hash_tuples :: [(String, String)]</div><div>    In the expression:</div><div>      do { buffer <- (hGetContents stdin) :: IO String;</div><div>           let filenames = ...;</div><div>           io_hash_tuples <- map do_prefix_hash filenames ::</div><div>                               [(IO String, String)];</div><div>           hash_tuples <- sequence io_hash_tuples :: [(String, String)];</div><div>           .... }</div><div>    In an equation for `main':</div><div>        main</div><div>          = do { buffer <- (hGetContents stdin) :: IO String;</div><div>                 let filenames = ...;</div><div>                 io_hash_tuples <- map do_prefix_hash filenames ::</div><div>                                     [(IO String, String)];</div><div>                 .... }</div><div><br></div><div>dph.hs:25:29:</div><div>    Couldn't match expected type `[[a0]]'</div><div>                with actual type `(IO String, String)'</div><div>    In the first argument of `sequence', namely `io_hash_tuples'</div><div>    In a stmt of a 'do' block:</div><div>      hash_tuples <- sequence io_hash_tuples :: [(String, String)]</div><div>    In the expression:</div><div>      do { buffer <- (hGetContents stdin) :: IO String;</div><div>           let filenames = ...;</div><div>           io_hash_tuples <- map do_prefix_hash filenames ::</div><div>                               [(IO String, String)];</div><div>           hash_tuples <- sequence io_hash_tuples :: [(String, String)];</div><div>           .... }</div><div><br></div><div>dph.hs:26:39:</div><div>    Couldn't match expected type `[(String, String)]'</div><div>                with actual type `(String, String)'</div><div>    In the second argument of `map', namely `hash_tuples'</div><div>    In the expression: map tuple_to_string hash_tuples :: [String]</div><div>    In an equation for `strings':</div><div>        strings = map tuple_to_string hash_tuples :: [String]</div><div>make: *** [dph] Error 1</div><div>above cmd output done    2015 Tue Dec 01 04:05:18 PM PST</div></div><div><br></div><div><br></div><div>dph.hs looks like:</div><div><div>import Md5s</div><div>import Split0</div><div>import System.IO</div><div><br></div><div>get_filenames :: String -> [String]</div><div>get_filenames buffer = do</div><div>    -- Let's hope this doesn't give locale-related roundtrip problems.</div><div>    Split0.split0 '\0' buffer :: [String]</div><div><br></div><div>do_prefix_hash :: String -> (IO String, String)</div><div>do_prefix_hash filename = do</div><div>    hash <- Md5s.prefix_md5 filename :: (IO String)</div><div>    (hash, filename)</div><div><br></div><div>tuple_to_string :: (String, String) -> String</div><div>tuple_to_string (first, second) = do</div><div>    (show first) ++ " " ++ (show second)</div><div><br></div><div>main :: IO ()</div><div>main = do</div><div>    buffer <- (System.IO.hGetContents System.IO.stdin) :: IO String</div><div>    let filenames = (get_filenames buffer) :: [String]</div><div>    io_hash_tuples <- map do_prefix_hash filenames :: [(IO String, String)]</div><div>    hash_tuples <- sequence io_hash_tuples :: [(String, String)]</div><div>    let strings = map tuple_to_string hash_tuples :: [String]</div><div>    mapM_ putStrLn strings</div></div><div><br></div><div><br></div><div>And Md5s.hs looks like:</div><div><div>module Md5s where</div><div><br></div><div>import qualified System.IO</div><div>import qualified Text.Printf</div><div>-- cabal install cryptohash</div><div>import qualified Crypto.Hash.MD5</div><div>import qualified Data.ByteString</div><div>import qualified Data.ByteString.Lazy</div><div><br></div><div>-- <a href="http://stackoverflow.com/questions/10099921/efficiently-turn-a-bytestring-into-a-hex-representation">http://stackoverflow.com/questions/10099921/efficiently-turn-a-bytestring-into-a-hex-representation</a></div><div>byte_string_to_hex :: Data.ByteString.ByteString -> String</div><div>byte_string_to_hex = concatMap (Text.Printf.printf "%02x") . Data.ByteString.unpack</div><div><br></div><div>prefix_md5 :: String -> IO String</div><div>prefix_md5 filename = do</div><div>    let prefix_length = 1024</div><div>    file <- System.IO.openBinaryFile filename System.IO.ReadMode :: IO System.IO.Handle</div><div>    data_read <- Data.ByteString.hGet file prefix_length :: IO Data.ByteString.ByteString</div><div>    _ <- System.IO.hClose file</div><div>    let hasher = Crypto.Hash.MD5.init :: Crypto.Hash.MD5.Ctx</div><div>    let hasher2 = Crypto.Hash.MD5.update hasher data_read :: Crypto.Hash.MD5.Ctx</div><div>    let binary_digest = Crypto.Hash.MD5.finalize hasher2 :: Data.ByteString.ByteString</div><div>    let hex_digest = byte_string_to_hex binary_digest :: String</div><div>    return hex_digest :: IO String</div><div><br></div><div>full_md5 :: String -> IO String</div><div>full_md5 filename = do</div><div>    file <- System.IO.openBinaryFile filename System.IO.ReadMode :: IO System.IO.Handle</div><div>    data_read <- Data.ByteString.Lazy.hGetContents file :: IO Data.ByteString.Lazy.ByteString</div><div>    let binary_digest = Crypto.Hash.MD5.hashlazy data_read :: Data.ByteString.ByteString</div><div>    let hex_digest = byte_string_to_hex binary_digest :: String</div><div>    -- Does this get closed for us later?</div><div>    -- strace shows the file getting closed without our explicit close.</div><div>    -- _ <- System.IO.hClose file</div><div>    return hex_digest :: IO String</div></div><div><br></div><div><br></div><div>It might be easier to view these at <a href="http://stromberg.dnsalias.org/svn/equivalence-classes/trunk/equivs3-haskell/">http://stromberg.dnsalias.org/svn/equivalence-classes/trunk/equivs3-haskell/</a> , so the line numbers are precise.</div><div><br></div><div>What is the deal?</div><div><br></div><div>Can anyone tell me what should be running through my head to fix this kind of problem on my own in the future?</div><div><br></div><div>Thanks!</div><div><br></div>-- <br><div class="gmail_signature">Dan Stromberg</div>
</div>