<div dir="ltr"><div><div><div><div><br></div>I read somewhere (probably Learn You a Haskell or Real-World Haskell) that beginners should use a lot of type declarations, but perhaps that's not a great idea after all.<br><br></div>Here's dph.hs without the type declarations and some abuses of do cleaned up:<br><br>import Md5s<br>import Split0<br>import System.IO<br><br>get_filenames :: String -> [String]<br>-- Let's hope this doesn't give locale-related roundtrip problems.<br>get_filenames buffer = Split0.split0 '\0' buffer<br><br>do_prefix_hash :: String -> (IO String, String)<br>do_prefix_hash filename = let hash = Md5s.prefix_md5 filename<br>                          in  (hash, filename)<br><br>tuple_to_string :: (String, String) -> String<br>tuple_to_string (first, second) = (show first) ++ " " ++ (show second)<br><br>main :: IO ()<br>main = do<br>    buffer <- (System.IO.hGetContents System.IO.stdin)<br>    let filenames = (get_filenames buffer)<br>    io_hash_tuples <- map do_prefix_hash filenames<br>    hash_tuples <- sequence io_hash_tuples<br>    let strings = map tuple_to_string hash_tuples<br>    mapM_ putStrLn strings<br><br></div>The (far fewer) errors I get now are:<br>dph.hs:21:23:<br>    Couldn't match type `[]' with `IO'<br>    Expected type: IO (IO String, String)<br>      Actual type: [(IO String, String)]<br>    In the return type of a call of `map'<br>    In a stmt of a 'do' block:<br>      io_hash_tuples <- map do_prefix_hash filenames<br>    In the expression:<br>      do { buffer <- (hGetContents stdin);<br>           let filenames = (get_filenames buffer);<br>           io_hash_tuples <- map do_prefix_hash filenames;<br>           hash_tuples <- sequence io_hash_tuples;<br>           .... }<br><br>dph.hs:22:29:<br>    Couldn't match expected type `[IO (String, String)]'<br>                with actual type `(IO String, String)'<br>    In the first argument of `sequence', namely `io_hash_tuples'<br>    In a stmt of a 'do' block: hash_tuples <- sequence io_hash_tuples<br>    In the expression:<br>      do { buffer <- (hGetContents stdin);<br>           let filenames = (get_filenames buffer);<br>           io_hash_tuples <- map do_prefix_hash filenames;<br>           hash_tuples <- sequence io_hash_tuples;<br>           .... }<br><br></div>I'm continuing to study Learn You a Haskell, though I'd kinda like to continue coding on this project in parallel.<br><div><div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Dec 1, 2015 at 7:47 PM, Simon Jakobi <span dir="ltr"><<a href="mailto:simon.jakobi@googlemail.com" target="_blank">simon.jakobi@googlemail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Dan,<br>
<br>
I'm having a hard time understanding those error messages too. It<br>
seems to me that part of the problem is that GHC is confused by some<br>
incorrect type annotations of yours.<br>
<br>
I suggest that you delete or at least comment out your own type<br>
annotations and then either work with the hopefully simpler error-messages<br>
from GHC or use the `:load` and `:type` commands in ghci to discover<br>
the inferred<br>
types for your functions.<br>
<br>
Depending on how close the inferred type is to the intended type, you<br>
may have to adjust the definitions.<br>
<br>
Also note that you sometimes incorrectly and unnecessarily use<br>
do-notation in "non-monadic"/plain functions, for example in<br>
tuple_to_string and get_filenames.<br>
<br>
You could also consider following a book or a course until you feel<br>
more comfortable trying things on your own:<br>
Take a look at <a href="http://learnyouahaskell.com" rel="noreferrer" target="_blank">learnyouahaskell.com</a> or <a href="http://github.com/bitemyapp/learnhaskell" rel="noreferrer" target="_blank">github.com/bitemyapp/learnhaskell</a>.<br>
<br>
Good luck!<br>
Simon<br>
<div><div class="h5"><br>
2015-12-02 1:12 GMT+01:00, Dan Stromberg <<a href="mailto:strombrg@gmail.com">strombrg@gmail.com</a>>:<br>
> I'm continuing my now-and-then exploration of Haskell.<br>
><br>
> I'm getting a new crop of type errors that I'm pulling my hair out over.<br>
><br>
> The errors I'm getting are:<br>
><br>
> $ make<br>
> below cmd output started 2015 Tue Dec 01 04:05:17 PM PST<br>
> # --make will go out and find what to build<br>
> ghc -Wall --make -o dph dph.hs Split0.hs<br>
> [1 of 3] Compiling Split0           ( Split0.hs, Split0.o )<br>
> [2 of 3] Compiling Md5s             ( Md5s.hs, Md5s.o )<br>
> [3 of 3] Compiling Main             ( dph.hs, dph.o )<br>
><br>
> dph.hs:13:13:<br>
>     Couldn't match type `IO' with `(,) (IO String)'<br>
>     Expected type: (IO String, String)<br>
>       Actual type: IO String<br>
>     In a stmt of a 'do' block: hash <- prefix_md5 filename :: IO String<br>
>     In the expression:<br>
>       do { hash <- prefix_md5 filename :: IO String;<br>
>            (hash, filename) }<br>
>     In an equation for `do_prefix_hash':<br>
>         do_prefix_hash filename<br>
>           = do { hash <- prefix_md5 filename :: IO String;<br>
>                  (hash, filename) }<br>
><br>
> dph.hs:14:6:<br>
>     Couldn't match type `[Char]' with `IO String'<br>
>     Expected type: IO String<br>
>       Actual type: String<br>
>     In the expression: hash<br>
>     In a stmt of a 'do' block: (hash, filename)<br>
>     In the expression:<br>
>       do { hash <- prefix_md5 filename :: IO String;<br>
>            (hash, filename) }<br>
><br>
> dph.hs:24:23:<br>
>     Couldn't match type `[]' with `IO'<br>
>     Expected type: IO (IO String, String)<br>
>       Actual type: [(IO String, String)]<br>
>     In a stmt of a 'do' block:<br>
>       io_hash_tuples <- map do_prefix_hash filenames ::<br>
>                           [(IO String, String)]<br>
>     In the expression:<br>
>       do { buffer <- (hGetContents stdin) :: IO String;<br>
>            let filenames = ...;<br>
>            io_hash_tuples <- map do_prefix_hash filenames ::<br>
>                                [(IO String, String)];<br>
>            hash_tuples <- sequence io_hash_tuples :: [(String, String)];<br>
>            .... }<br>
>     In an equation for `main':<br>
>         main<br>
>           = do { buffer <- (hGetContents stdin) :: IO String;<br>
>                  let filenames = ...;<br>
>                  io_hash_tuples <- map do_prefix_hash filenames ::<br>
>                                      [(IO String, String)];<br>
>                  .... }<br>
><br>
> dph.hs:25:20:<br>
>     Couldn't match type `[a0]' with `(String, String)'<br>
>     Expected type: [(String, String)]<br>
>       Actual type: [[a0]]<br>
>     In the return type of a call of `sequence'<br>
>     In a stmt of a 'do' block:<br>
>       hash_tuples <- sequence io_hash_tuples :: [(String, String)]<br>
>     In the expression:<br>
>       do { buffer <- (hGetContents stdin) :: IO String;<br>
>            let filenames = ...;<br>
>            io_hash_tuples <- map do_prefix_hash filenames ::<br>
>                                [(IO String, String)];<br>
>            hash_tuples <- sequence io_hash_tuples :: [(String, String)];<br>
>            .... }<br>
><br>
> dph.hs:25:20:<br>
>     Couldn't match type `[]' with `IO'<br>
>     Expected type: IO (String, String)<br>
>       Actual type: [(String, String)]<br>
>     In a stmt of a 'do' block:<br>
>       hash_tuples <- sequence io_hash_tuples :: [(String, String)]<br>
>     In the expression:<br>
>       do { buffer <- (hGetContents stdin) :: IO String;<br>
>            let filenames = ...;<br>
>            io_hash_tuples <- map do_prefix_hash filenames ::<br>
>                                [(IO String, String)];<br>
>            hash_tuples <- sequence io_hash_tuples :: [(String, String)];<br>
>            .... }<br>
>     In an equation for `main':<br>
>         main<br>
>           = do { buffer <- (hGetContents stdin) :: IO String;<br>
>                  let filenames = ...;<br>
>                  io_hash_tuples <- map do_prefix_hash filenames ::<br>
>                                      [(IO String, String)];<br>
>                  .... }<br>
><br>
> dph.hs:25:29:<br>
>     Couldn't match expected type `[[a0]]'<br>
>                 with actual type `(IO String, String)'<br>
>     In the first argument of `sequence', namely `io_hash_tuples'<br>
>     In a stmt of a 'do' block:<br>
>       hash_tuples <- sequence io_hash_tuples :: [(String, String)]<br>
>     In the expression:<br>
>       do { buffer <- (hGetContents stdin) :: IO String;<br>
>            let filenames = ...;<br>
>            io_hash_tuples <- map do_prefix_hash filenames ::<br>
>                                [(IO String, String)];<br>
>            hash_tuples <- sequence io_hash_tuples :: [(String, String)];<br>
>            .... }<br>
><br>
> dph.hs:26:39:<br>
>     Couldn't match expected type `[(String, String)]'<br>
>                 with actual type `(String, String)'<br>
>     In the second argument of `map', namely `hash_tuples'<br>
>     In the expression: map tuple_to_string hash_tuples :: [String]<br>
>     In an equation for `strings':<br>
>         strings = map tuple_to_string hash_tuples :: [String]<br>
> make: *** [dph] Error 1<br>
> above cmd output done    2015 Tue Dec 01 04:05:18 PM PST<br>
><br>
><br>
> dph.hs looks like:<br>
> import Md5s<br>
> import Split0<br>
> import System.IO<br>
><br>
> get_filenames :: String -> [String]<br>
> get_filenames buffer = do<br>
>     -- Let's hope this doesn't give locale-related roundtrip problems.<br>
>     Split0.split0 '\0' buffer :: [String]<br>
><br>
> do_prefix_hash :: String -> (IO String, String)<br>
> do_prefix_hash filename = do<br>
>     hash <- Md5s.prefix_md5 filename :: (IO String)<br>
>     (hash, filename)<br>
><br>
> tuple_to_string :: (String, String) -> String<br>
> tuple_to_string (first, second) = do<br>
>     (show first) ++ " " ++ (show second)<br>
><br>
> main :: IO ()<br>
> main = do<br>
>     buffer <- (System.IO.hGetContents System.IO.stdin) :: IO String<br>
>     let filenames = (get_filenames buffer) :: [String]<br>
>     io_hash_tuples <- map do_prefix_hash filenames :: [(IO String, String)]<br>
>     hash_tuples <- sequence io_hash_tuples :: [(String, String)]<br>
>     let strings = map tuple_to_string hash_tuples :: [String]<br>
>     mapM_ putStrLn strings<br>
><br>
><br>
> And Md5s.hs looks like:<br>
> module Md5s where<br>
><br>
> import qualified System.IO<br>
> import qualified Text.Printf<br>
> -- cabal install cryptohash<br>
> import qualified Crypto.Hash.MD5<br>
> import qualified Data.ByteString<br>
> import qualified Data.ByteString.Lazy<br>
><br>
> --<br>
> <a href="http://stackoverflow.com/questions/10099921/efficiently-turn-a-bytestring-into-a-hex-representation" rel="noreferrer" target="_blank">http://stackoverflow.com/questions/10099921/efficiently-turn-a-bytestring-into-a-hex-representation</a><br>
> byte_string_to_hex :: Data.ByteString.ByteString -> String<br>
> byte_string_to_hex = concatMap (Text.Printf.printf "%02x") .<br>
> Data.ByteString.unpack<br>
><br>
> prefix_md5 :: String -> IO String<br>
> prefix_md5 filename = do<br>
>     let prefix_length = 1024<br>
>     file <- System.IO.openBinaryFile filename System.IO.ReadMode :: IO<br>
> System.IO.Handle<br>
>     data_read <- Data.ByteString.hGet file prefix_length :: IO<br>
> Data.ByteString.ByteString<br>
>     _ <- System.IO.hClose file<br>
>     let hasher = Crypto.Hash.MD5.init :: Crypto.Hash.MD5.Ctx<br>
>     let hasher2 = Crypto.Hash.MD5.update hasher data_read ::<br>
> Crypto.Hash.MD5.Ctx<br>
>     let binary_digest = Crypto.Hash.MD5.finalize hasher2 ::<br>
> Data.ByteString.ByteString<br>
>     let hex_digest = byte_string_to_hex binary_digest :: String<br>
>     return hex_digest :: IO String<br>
><br>
> full_md5 :: String -> IO String<br>
> full_md5 filename = do<br>
>     file <- System.IO.openBinaryFile filename System.IO.ReadMode :: IO<br>
> System.IO.Handle<br>
>     data_read <- Data.ByteString.Lazy.hGetContents file :: IO<br>
> Data.ByteString.Lazy.ByteString<br>
>     let binary_digest = Crypto.Hash.MD5.hashlazy data_read ::<br>
> Data.ByteString.ByteString<br>
>     let hex_digest = byte_string_to_hex binary_digest :: String<br>
>     -- Does this get closed for us later?<br>
>     -- strace shows the file getting closed without our explicit close.<br>
>     -- _ <- System.IO.hClose file<br>
>     return hex_digest :: IO String<br>
><br>
><br>
> It might be easier to view these at<br>
> <a href="http://stromberg.dnsalias.org/svn/equivalence-classes/trunk/equivs3-haskell/" rel="noreferrer" target="_blank">http://stromberg.dnsalias.org/svn/equivalence-classes/trunk/equivs3-haskell/</a><br>
> , so the line numbers are precise.<br>
><br>
> What is the deal?<br>
><br>
> Can anyone tell me what should be running through my head to fix this kind<br>
> of problem on my own in the future?<br>
><br>
> Thanks!<br>
><br>
> --<br>
> Dan Stromberg<br>
><br>
</div></div>_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners</a><br>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature">Dan Stromberg</div>
</div></div></div></div></div></div>