diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,5 +1,12 @@
 # Crypto Multihash
 
+[![Build Status](https://travis-ci.org/mseri/crypto-multihash.svg?branch=master)](https://travis-ci.org/mseri/crypto-multihash)
+![Hackage](https://img.shields.io/hackage/v/crypto-multihash.svg)
+![Hackage Dependencies](https://img.shields.io/hackage-deps/v/crypto-multihash.svg)
+![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)
+![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)
+
+
 Multihash library implemented on top of [cryptonite](https://hackage.haskell.org/package/cryptonite) cryptographic library. 
 Multihash is a protocol for encoding the hash algorithm and digest length at the start of the digest, see the official [multihash github page](https://github.com/jbenet/multihash/).
 
@@ -17,21 +24,55 @@
 
 import Crypto.Multihash
 import Data.ByteString (ByteString)
+import Data.ByteString.Char8 (pack)
 
 main = do
-    let m = multihash SHA256 ("test"::ByteString)
+    let v = "test"::ByteString
+    let m = multihash SHA256 v
     putStrLn $ "Base16: " ++ (encode Base16 m)
     putStrLn $ "Base58: " ++ (encode Base58 m)
     putStrLn $ "Base64: " ++ (encode Base64 m)
+    
+    let h = encode' Base58 m
+    let h8 = (Data.ByteString.Char8.pack h)
+    checkMultihash h8 v
+    -- Right True
 ```
 
 # Test
 
-Some preliminary tests can be performed with `stack test`.
-A simple example encoder is in `app/Main.hs`. You can run it on files (e.g. `echo -n test | stack exec mh -- somefile someotherfile`) or read data from the standard input (e.g. `echo -n test | stack exec mh -- -`)
+Some preliminary tests can be performed with `stack test`. 
 
+A simple example encoder is in `app/Main.hs`. 
+You can run it on files
+
+```{.bash}
+echo -n test | stack exec mh -- somefile someotherfile
+```
+
+or read data from the standard input 
+
+```{.bash}
+echo -n test | stack exec mh -- -`
+```
+
+# Contribution
+
+1. Fork repository
+2. Do some changes
+3. Create pull request
+4. Wait for CI build and review
+
+You can use stack to build the project: `stack build`
+
+To run tests: `stack test`
+
 # TODO
-- Implement hash checker that takes some data and an encoded multihash and check that the multihash corresponds to the data (inferring automatically the appropriate hash function)
-- Evaluate if throwing an error in the encode function is the wanted behaviour and anyway implement a safe version returning an Either type
+
+- ~~Improve documentation~~
+- ~~Implement hash checker that takes some data and an encoded multihash and check that the multihash corresponds to the data (inferring automatically the appropriate hash function)~~
+- ~~Evaluate if throwing an error in the encode function is the wanted behaviour and anyway implement a safe version returning an Either type~~
+- Add testing for the newly introduced checker and for raised exceptions
+- Add multihash checker into the cli example
 - Implement `shake-128` and `shake-256` multihashes
-- Implement `Base32` encoding
+- Implement `Base32` encoding waiting for https://github.com/jbenet/multihash/issues/31 to be resolved)
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -2,7 +2,6 @@
 
 module Main where
 
-import Control.Monad
 import Crypto.Multihash
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
@@ -15,7 +14,7 @@
 
 main :: IO ()
 main = do
-  (args, files) <- getArgs >>= parse
+  (_args, files) <- getArgs >>= parse
   mapM_ printers files
   putStrLn "Done! Note: shake-128/256 and Base32 are not yet part of the library"
  
@@ -23,12 +22,13 @@
 printer alg bs = do
   let m = multihash alg bs
   putStrLn $ printf "Hash algorithm: %s" (show alg)
-  putStrLn $ printf "Base16: %s" (encode Base16 m)
+  putStrLn $ printf "Base16: %s" (encode' Base16 m)
   -- Base32 missing
-  putStrLn $ printf "Base58: %s" (encode Base58 m)
-  putStrLn $ printf "Base64: %s" (encode Base64 m)
+  putStrLn $ printf "Base58: %s" (encode' Base58 m)
+  putStrLn $ printf "Base64: %s" (encode' Base64 m)
   putStrLn ""
 
+printers :: FilePath -> IO ()
 printers f = do
   d <- withFile f
   putStrLn $ printf "Hashing %s\n" (if f == "-" then show d else show f)
@@ -47,8 +47,10 @@
 data Flag = Help                  -- --help
           deriving (Eq,Ord,Enum,Show,Bounded)
  
+flags :: [OptDescr Flag]
 flags = [Option [] ["help"] (NoArg Help) "Print this help message"]
- 
+
+parse :: [String] -> IO ([Flag], [String])
 parse argv = case getOpt Permute flags argv of
     (args,fs,[]) -> do
         let files = if null fs then ["-"] else fs
diff --git a/crypto-multihash.cabal b/crypto-multihash.cabal
--- a/crypto-multihash.cabal
+++ b/crypto-multihash.cabal
@@ -1,5 +1,5 @@
 name:                crypto-multihash
-version:             0.1.0.0
+version:             0.2.0.0
 synopsis:            Multihash library on top of cryptonite crypto library
 description:         Multihash is a protocol for encoding the hash algorithm
                      and digest length at the start of the digest, see the official
@@ -20,6 +20,7 @@
 library
   hs-source-dirs:      src
   exposed-modules:     Crypto.Multihash
+  ghc-options:         -Wall -fwarn-tabs -fno-warn-name-shadowing -fwarn-pointless-pragmas
   build-depends:       base >= 4.7 && < 5
                      , base58-bytestring
                      , bytestring
diff --git a/src/Crypto/Multihash.hs b/src/Crypto/Multihash.hs
--- a/src/Crypto/Multihash.hs
+++ b/src/Crypto/Multihash.hs
@@ -1,8 +1,37 @@
+-- |
+-- Module      : Crypto.Multihash
+-- License     : BSD3
+-- Maintainer  : Marcello Seri <marcello.seri@gmail.com>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- Multihash library built on top of haskell 'cryptonite' crypto package
+-- Multihash is a protocol for encoding the hash algorithm and digest length 
+-- at the start of the digest, see the official 
+-- <https://github.com/jbenet/multihash/ multihash poroposal github repo>.
+--
+-- The library re-exports the needed types and typclasses from 'Crypto.Hash.Algorithms'
+-- namely 'HashAlgorithm', 'SHA1', 'SHA256', 'SHA512', 'SHA3_512', 'SHA3_384',
+-- 'SHA3_256', 'SHA3_224', 'Blake2b_512', 'Blake2s_256'. 
+--
+-- For additional informations refer to the README.md or the
+-- <https://github.com/mseri/crypto-multihash gihub repository>.
+--
+{-# LANGUAGE OverloadedStrings #-}
+
 module Crypto.Multihash
-  ( MultihashDigest
+  ( -- * Multihash Types
+    MultihashDigest
   , Base            (..)
   , Codable         (..)
-  , HashAlgorithm   (..)
+  -- * Multihash helpers
+  , encode
+  , encode'
+  , multihash
+  , multihashlazy
+  , checkMultihash
+  -- * Re-exported types
+  , HashAlgorithm
   , SHA1(..)
   , SHA256(..)
   , SHA512(..)
@@ -12,37 +41,40 @@
   , SHA3_224(..)
   , Blake2b_512(..)
   , Blake2s_256(..)
-  , encode
-  , multihash
-  , multihashlazy
   ) where
 
-import Crypto.Hash (HashAlgorithm(..), Digest(..), hash, hashlazy)
+import Crypto.Hash (HashAlgorithm(..), Digest, hash, hashlazy)
 import Crypto.Hash.Algorithms
-import Crypto.Hash.IO
+--import Crypto.Hash.IO
 import Data.ByteArray (ByteArrayAccess, Bytes)
 import qualified Data.ByteArray as BA
 import qualified Data.ByteArray.Encoding as BE
 import qualified Data.ByteString as BS
+import qualified Data.ByteString.Char8 as C
 import qualified Data.ByteString.Lazy as BL
 import qualified Data.ByteString.Base58 as B58
+import Data.List (findIndex)
 import Data.Word (Word8)
 import Text.Printf (printf)
 
-data Base = Base16  -- ^ Hex encoding
-          | Base32  -- ^ Not implemented. For reasons that I did not investigate, the instance in Data.ByteArray produces output not conformant with the multihash spec.
-          | Base58  -- ^ Bitcoin Base58 encoding, the one used also by IPFS
+-- | 'Base' usable to encode the digest 
+data Base = Base2   -- ^ Binary form
+          | Base16  -- ^ Hex encoding
+          | Base32  -- ^ Not yet implemented. Waiting for <https://github.com/jbenet/multihash/issues/31 this issue to resolve>
+          | Base58  -- ^ Bitcoin base58 encoding
           | Base64  -- ^ Base64 encoding
-          deriving (Eq)
+          deriving (Show, Eq)
 
 -- | Multihash Digest container
 data MultihashDigest a = MultihashDigest
-  { getAlgorithm :: a
-  , getLength :: Int
-  , getDigest :: Digest a
-  }
+  { getAlgorithm :: a     -- ^ hash algorithm
+  , getLength :: Int      -- ^ hash lenght
+  , getDigest :: Digest a -- ^ binary digest data
+  } deriving (Eq)
 
+-- | 'Codable' hash algorithms are the algorithms supported for multihashing
 class Codable a where
+  -- | Returns the first byte for the head of the multihash digest
   toCode :: a -> Int
 
 instance Codable SHA1 where
@@ -71,34 +103,40 @@
 instance Show (MultihashDigest a) where
     show (MultihashDigest _ _ d) = show d
 
+-- | Helper to multihash a lazy 'ByteString' using a supported hash algorithm.
 multihashlazy :: (HashAlgorithm a, Codable a) => a -> BL.ByteString -> MultihashDigest a
 multihashlazy alg bs = let digest = (hashlazy bs) 
                        in MultihashDigest alg (BA.length digest) digest
 
+-- | Helper to multihash a 'ByteArrayAccess' (e.g. a 'ByteString') using a supported hash algorithm.
 multihash :: (HashAlgorithm a, Codable a, ByteArrayAccess bs) => a -> bs -> MultihashDigest a
 multihash alg bs = let digest = (hash bs) 
                    in MultihashDigest alg (BA.length digest) digest
 
--- | Encoder for 'Multihash'es.
---   Throws an error if the Multihash length field does not match the Digest length
-encode :: (HashAlgorithm a, Codable a, Show a) => Base -> MultihashDigest a -> String
+
+-- | Safe encoder for 'MultihashDigest'.
+encode :: (HashAlgorithm a, Codable a, Show a) => Base -> MultihashDigest a -> Either String String
 encode base (MultihashDigest alg len md) = if len == len'
-    then map (toEnum . fromIntegral) fullDigestUnpacked
-    else error $ printf "Corrupted %s MultihashDigest. Lenght is %d but should be %d." (show alg) len len'
+    then do
+      d <- fullDigestUnpacked
+      return $ map (toEnum . fromIntegral) d
+    else Left $ printf "Corrupted %s MultihashDigest. Lenght is %d but should be %d." (show alg) len len'
   where
     len' :: Int
     len' = BA.length md
 
-    fullDigestUnpacked :: [Word8]
-    fullDigestUnpacked = BA.unpack $ encoder fullDigest
+    fullDigestUnpacked :: Either String [Word8]
+    fullDigestUnpacked = do
+      d <- encoder fullDigest
+      return $ BA.unpack d
       where 
-        encoder :: ByteArrayAccess a => a -> Bytes
+        encoder :: ByteArrayAccess a => a -> Either String Bytes
         encoder bs = case base of
-                    --Base2  -> BA.convert $ bs
-                    Base16 -> BE.convertToBase BE.Base16 bs
-                    Base32 -> error "Base32 encoder not implemented"
-                    Base58 -> BA.convert $ B58.encodeBase58 B58.bitcoinAlphabet $ (BA.convert bs :: BS.ByteString)
-                    Base64 -> BE.convertToBase BE.Base64 bs
+                    Base2  -> return $ BA.convert $ bs
+                    Base16 -> return $ BE.convertToBase BE.Base16 bs
+                    Base32 -> Left "Base32 encoder not implemented"
+                    Base58 -> return $ BA.convert $ B58.encodeBase58 B58.bitcoinAlphabet $ (BA.convert bs :: BS.ByteString)
+                    Base64 -> return $ BE.convertToBase BE.Base64 bs
 
     fullDigest :: Bytes
     fullDigest = BA.pack [dHead, dSize] `BA.append` dTail
@@ -110,20 +148,70 @@
         dTail :: Bytes
         dTail = BA.convert md
 
---checkHash :: Base -> String -> 
+-- | Encoder for 'MultihashDigest'.
+--   Throws an error if the 'MultihashDigest' length field does not match the 'Digest' length.
+encode' :: (HashAlgorithm a, Codable a, Show a) => Base -> MultihashDigest a -> String
+encode' base md = 
+  case encode base md of
+    Right enc -> enc
+    Left err  -> error err
 
--- data MultihashAlgorithm = S1 SHA1 | S256 SHA256 | S512 SHA512 
---                         | S3512 SHA3_512 | S3384 SHA3_384 | S3256 SHA3_256 | S3224 SHA3_224
---                         | B2b Blake2b_512 | B2s Blake2s_256
+-- | Check the correctness of an encoded 'MultihashDigest' against the data it
+--   is supposed to have hashed, passed as a 'ByteArrayAccess' (e.g. a 'BinaryString').
+checkMultihash :: ByteArrayAccess bs => BS.ByteString -> bs -> Either String Bool
+checkMultihash hash unahshedData = do
+  base <- getBase hash
+  mhd <- convertFromBase base hash
+  m <- getBinaryEncodedMultihash mhd unahshedData
+  -- Hacky... think to a different approach
+  return (C.pack m == mhd)
 
--- toCode :: MultihashAlgorithm -> Int
--- toCode (S1 SHA1)        = 0x11
--- toCode (S256 SHA256)      = 0x12
--- toCode (S512 SHA512)      = 0x13
--- toCode (S3512 SHA3_512)    = 0x14
--- toCode (S3384 SHA3_384)    = 0x15
--- toCode (S3256 SHA3_256)    = 0x16
--- toCode (S3224 SHA3_224)    = 0x17
--- toCode (B2b Blake2b_512) = 0x40
--- toCode (B2s Blake2s_256) = 0x41
--- toCode _           = error "Multihash: unknown or unimplemented hash function code"
+-- Helpers
+
+maybeToEither :: l -> Maybe r -> Either l r
+maybeToEither _ (Just res) = Right res
+maybeToEither err _        = Left err
+
+-- | Convert a 'ByteString' from a 'Base' into a 'BinaryString' in 'Base2'.
+convertFromBase :: Base -> BS.ByteString -> Either String BS.ByteString
+convertFromBase b bs = case b of
+  Base2  -> Left "This is not supposed to happen"
+  Base16 -> BE.convertFromBase BE.Base16 bs
+  Base32 -> Left "Base32 decoder not implemented"
+  Base58 -> do
+    dec <- maybeToEither "Base58 decoding error" (B58.decodeBase58 B58.bitcoinAlphabet bs)
+    return (BA.convert dec)
+  Base64 -> BE.convertFromBase BE.Base64 bs
+
+-- | Infer the 'Base' encoding function from an encoded 'BinaryString' representing 
+-- a 'MultihashDigest'.
+getBase :: BS.ByteString -> Either String Base
+getBase h
+      | startWiths h ["1114", "1220", "1340", "1440", "1530", "1620", "171c", "4040", "4120"] = Right Base16
+      | startWiths h ["5d", "Qm", "8V", "8t", "G9", "W1", "5d", "S2", "2U"] = Right Base58
+      | startWiths h ["ER", "Ei", "E0", "FE", "FT", "Fi", "Fx", "QE", "QS"] = Right Base64
+      | otherwise = Left "Unable to infer an encoding"
+      where startWiths h ls = any (flip BS.isPrefixOf h) ls
+
+-- | Infer the hash function from an unencoded 'BinaryString' representing 
+-- a 'MultihashDigest' and uses it to binary encode the data in a 'MultihashDigest'.
+getBinaryEncodedMultihash :: ByteArrayAccess bs => BS.ByteString -> bs -> Either String String
+getBinaryEncodedMultihash mhd uh = let bitOne = head $ BS.unpack mhd in
+  case findIndex ((==) bitOne) hashCodes of
+    Just 0 -> rs SHA1 uh
+    Just 1 -> rs SHA256 uh
+    Just 2 -> rs SHA512 uh
+    Just 3 -> rs SHA3_512 uh
+    Just 4 -> rs SHA3_384 uh
+    Just 5 -> rs SHA3_256 uh
+    Just 6 -> rs SHA3_224 uh
+    Just 7 -> rs Blake2b_512 uh
+    Just 8 -> rs Blake2s_256 uh
+    Just _ -> Left "This should be impossible"
+    Nothing -> Left "Impossible to infer the appropriate hash from the header"
+  where 
+    rs alg = encode Base2 . multihash alg
+    hashCodes :: [Word8]
+    hashCodes = map (\i -> fromIntegral i) 
+                    ([0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x40, 0x41]::[Int])
+    mhdPrefix = flip BS.isPrefixOf mhd
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -40,11 +40,11 @@
     testMHEncoding alg (sm16, sm58, sm64) = do
         describe (printf "Encoding %s multihash" (show alg)) $ do
           it "returns the correct Base16 hash" $ 
-            encode Base16 m `shouldBe` sm16
+            encode' Base16 m `shouldBe` sm16
           it "returns the correct Base58 hash" $ 
-            encode Base58 m `shouldBe` sm58
+            encode' Base58 m `shouldBe` sm58
           it "returns the correct Base64 hash" $ 
-            encode Base64 m `shouldBe` sm64
+            encode' Base64 m `shouldBe` sm64
       where 
         m = multihash alg ("test"::ByteString)
   
