diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -7,3 +7,7 @@
 
 ## 0.1.0.2
 * Fixed Hackage metadata
+
+## 0.1.0.3
+* Up to 10% performance improvement
+* Additional explanations on the arguments of the core function
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -52,7 +52,10 @@
 ```
 
 ## How to build
-```bash
+```shell
+## Install 'stack' if not any
+$ brew install stack
+
 $ git clone https://github.com/thyeem/longshot.git
 
 $ make build 
@@ -65,7 +68,7 @@
 ```
 
 ## Quick start
-```bash
+```shell
 ## Refer to the following usage:
 ## Note that the order of arguments and options matter.
 $ ./longshot -h
@@ -96,7 +99,7 @@
 See below for more interesting detailed examples.
 
 ## More examples
-```bash
+```shell
 ## Generate a example image using Blake2b hash algorithm
 ## Blake2b-hashed sofia (my first daughter!)
 $ ./longshot image -a blake2b sofia
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -1,13 +1,13 @@
 {-# LANGUAGE QuasiQuotes #-}
 module Main where
 
-import           Control.Monad
-import           System.Environment
+import           Control.Monad                  ( when )
+import           System.Environment             ( getArgs )
 import           System.Console.Docopt
 import qualified Data.ByteString.Char8         as C
 import qualified Data.ByteString.Base16        as H
 import           Crypto.Longshot.Internal
-import           Crypto.Longshot.Hasher
+import           Crypto.Longshot.Hasher         ( getHasher )
 
 patterns :: Docopt
 patterns = [docopt|
diff --git a/longshot.cabal b/longshot.cabal
--- a/longshot.cabal
+++ b/longshot.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 4cf3d32f97b4605f2bd729574881eb5df14e31adef0431f928343ea04e268c38
+-- hash: 950eaac57e913aaa5d3f38ed066cb8aefb07851a8072f2686280220fd76aa711
 
 name:           longshot
-version:        0.1.0.2
+version:        0.1.0.3
 synopsis:       Fast Brute-force search using parallelism
 description:    Longshot enables to search for preimages from a given hash value
                 using a brute-force method based on parallelism.
@@ -41,6 +41,7 @@
 library
   exposed-modules:
       Crypto.Longshot
+      Crypto.Longshot.Const
       Crypto.Longshot.Hasher
       Crypto.Longshot.Internal
       Crypto.Longshot.TH
diff --git a/src/Crypto/Longshot.hs b/src/Crypto/Longshot.hs
--- a/src/Crypto/Longshot.hs
+++ b/src/Crypto/Longshot.hs
@@ -5,56 +5,21 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- How big is the search space? The space consists of two axes.
---
--- * X-axis: Number of characters available
--- * Y-axis: Search length of preimage to find
---
--- Note that it's proportional to @(X ^ Y)@ rather than @(X * Y)@
---
--- The values below are defined by default.
---
--- When not provided as options in CUI, the following values are used.
+-- Fast Brute-force search using parallelism
 --
-module Crypto.Longshot where
-
-import           Control.Monad
-import qualified Data.ByteString.Char8         as C
-import qualified Data.ByteString.Base16        as H
-
--- | Characters available in a preimage
-defChars :: String
-defChars = "0123456789"
-
--- | Search length of preimage
-defSearchLength :: Int
-defSearchLength = 8
-
--- | Limit search length of preimage
-limitSearchLength :: Int
-limitSearchLength = 20
-
--- | Value related to the number of sparks
-defNumPrefix :: Int
-defNumPrefix = 3
-
--- | Number of actions in TH bruteforceN
-defNumBind :: Int
-defNumBind = limitSearchLength - defNumPrefix
---------------------------------------------------------------------
-
--- | Image bytestring: target hash value to find
-image :: String -> C.ByteString
-image = fst . H.decode . C.pack
-
--- | Bytestring usable for preimage
-byteChars :: String -> [C.ByteString]
-byteChars chars = C.pack . (: []) <$> chars
-
--- | Combination of prefixes possible: size of (length of chars) ^ (numPrefix)
-bytePrefixes :: Int -> String -> [C.ByteString]
-bytePrefixes numPrefix chars = C.pack <$> replicateM numPrefix chars
+-- Longshot enables to search for preimages from a given hash value
+-- using a brute-force method based on parallelism.
+-- 
+module Crypto.Longshot
+  ( module Crypto.Longshot
+  , module Crypto.Longshot.Const
+  , module Crypto.Longshot.Internal
+  , module Crypto.Longshot.TH
+  , module Crypto.Longshot.Hasher
+  )
+where
 
--- | Convert preimage found into key string
-toKey :: C.ByteString -> String
-toKey = C.unpack
+import           Crypto.Longshot.Const
+import           Crypto.Longshot.Internal
+import           Crypto.Longshot.TH
+import           Crypto.Longshot.Hasher
diff --git a/src/Crypto/Longshot/Const.hs b/src/Crypto/Longshot/Const.hs
new file mode 100644
--- /dev/null
+++ b/src/Crypto/Longshot/Const.hs
@@ -0,0 +1,39 @@
+-- |
+-- Module      : Crypto.Longshot.Const
+-- License     : MIT
+-- Maintainer  : Francis Lim <thyeem@gmail.com>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- How big is the search space? The space consists of two axes.
+--
+-- * @X-axis@: Number of characters available
+-- * @Y-axis@: Search length of preimage to find
+--
+-- Note that it's proportional to @(X ^ Y)@ rather than @(X * Y)@
+--
+-- The values below are defined by default.
+--
+-- When not provided as options in CUI, the following values are used.
+--
+module Crypto.Longshot.Const where
+
+-- | Default characters available in a preimage
+defChars :: String
+defChars = "0123456789"
+
+-- | Default search length of preimage
+defSearchLength :: Int
+defSearchLength = 8
+
+-- | Limit search length of preimage
+limitSearchLength :: Int
+limitSearchLength = 20
+
+-- | Default value related to the number of sparks
+defNumPrefix :: Int
+defNumPrefix = 3
+
+-- | Maximum number of actions in bruteforceN
+maxNumBind :: Int
+maxNumBind = limitSearchLength - defNumPrefix
diff --git a/src/Crypto/Longshot/Hasher.hs b/src/Crypto/Longshot/Hasher.hs
--- a/src/Crypto/Longshot/Hasher.hs
+++ b/src/Crypto/Longshot/Hasher.hs
@@ -11,22 +11,21 @@
   )
 where
 
-import           GHC.TypeLits
-import           Numeric.Natural
+import           GHC.TypeLits                   ( Nat )
+import           Data.ByteString                ( ByteString )
 import qualified Data.ByteArray                as B
-import qualified Data.ByteString.Char8         as C
 import qualified Crypto.Hash                   as X
 import qualified Crypto.Hash.SHA256            as S
-import qualified Crypto.Hash.BLAKE2.BLAKE2s    as B2s
-import qualified Crypto.Hash.BLAKE2.BLAKE2b    as B2b
-import qualified BLAKE3                        as B3
+import qualified Crypto.Hash.BLAKE2.BLAKE2s    as Blake2s
+import qualified Crypto.Hash.BLAKE2.BLAKE2b    as Blake2b
+import qualified BLAKE3                        as Blake3
 
 -- | Type for hash functions available
-type Hasher = C.ByteString -> C.ByteString
+type Hasher = ByteString -> ByteString
 
-type Blake3_256 = C.ByteString -> B3.Digest (32 :: Nat)
-type Blake3_384 = C.ByteString -> B3.Digest (48 :: Nat)
-type Blake3_512 = C.ByteString -> B3.Digest (64 :: Nat)
+type Blake3_256 = ByteString -> Blake3.Digest (32 :: Nat)
+type Blake3_384 = ByteString -> Blake3.Digest (48 :: Nat)
+type Blake3_512 = ByteString -> Blake3.Digest (64 :: Nat)
 
 -- | Select hasher by defined name
 getHasher :: String -> Hasher
@@ -39,13 +38,13 @@
   "sha3_256"    -> B.convert . X.hashWith X.SHA3_256
   "sha3_384"    -> B.convert . X.hashWith X.SHA3_384
   "sha3_512"    -> B.convert . X.hashWith X.SHA3_512
-  "blake2s_256" -> B2s.hash 32 mempty
-  "blake2b_256" -> B2b.hash 32 mempty
-  "blake2b_384" -> B2b.hash 48 mempty
-  "blake2b_512" -> B2b.hash 64 mempty
-  "blake3_256"  -> B.convert . (B3.hash . (: []) :: Blake3_256)
-  "blake3_384"  -> B.convert . (B3.hash . (: []) :: Blake3_384)
-  "blake3_512"  -> B.convert . (B3.hash . (: []) :: Blake3_512)
+  "blake2s_256" -> Blake2s.hash 32 mempty
+  "blake2b_256" -> Blake2b.hash 32 mempty
+  "blake2b_384" -> Blake2b.hash 48 mempty
+  "blake2b_512" -> Blake2b.hash 64 mempty
+  "blake3_256"  -> B.convert . (Blake3.hash . (: []) :: Blake3_256)
+  "blake3_384"  -> B.convert . (Blake3.hash . (: []) :: Blake3_384)
+  "blake3_512"  -> B.convert . (Blake3.hash . (: []) :: Blake3_512)
   "keccak_256"  -> B.convert . X.hashWith X.Keccak_256
   "keccak_384"  -> B.convert . X.hashWith X.Keccak_384
   "keccak_512"  -> B.convert . X.hashWith X.Keccak_512
diff --git a/src/Crypto/Longshot/Internal.hs b/src/Crypto/Longshot/Internal.hs
--- a/src/Crypto/Longshot/Internal.hs
+++ b/src/Crypto/Longshot/Internal.hs
@@ -8,23 +8,59 @@
 module Crypto.Longshot.Internal
   ( bruteforce
   , bruteforceDeep
+  , bruteforcePar
+  , (<%>)
+  , image
+  , byteChars
+  , bytePrefixes
   )
 where
 
-import           Control.Applicative
-import           Control.DeepSeq
-import           Control.Parallel
-import           Data.Foldable
+import           Control.Monad                  ( replicateM )
+import           Control.Applicative            ( (<|>)
+                                                , empty
+                                                )
+import           Control.Parallel               ( par
+                                                , pseq
+                                                )
+import           Control.DeepSeq                ( NFData
+                                                , force
+                                                )
+import           Data.Foldable                  ( foldl' )
+import           Data.ByteString                ( ByteString )
 import qualified Data.ByteString.Char8         as C
-import           Language.Haskell.TH
-import           Crypto.Longshot
-import           Crypto.Longshot.TH
+import qualified Data.ByteString.Base16        as H
 import           Crypto.Longshot.Hasher
+import           Crypto.Longshot.TH
+import           Crypto.Longshot.Const
 
--- Declaration of bruteforceN: generating code by splicing
+-- | Each bruteforceN declaration: generating code through splicing.
+-- Number of functions declared == 'maxNumBind'
+--
 $( funcGenerator )
 
 -- | Brute-force search only for a given exact length
+--
+-- @
+-- ------------------------------------------------------------------------------
+--     size | Preimage length to search
+-- ------------------------------------------------------------------------------
+--    chars | Given character set like "0123456789"
+-- ------------------------------------------------------------------------------
+--      hex | Given hex-string like "17da1ae431f965d839ec8eb93087fb2b"
+-- ------------------------------------------------------------------------------
+--   hasher | Hash functions in 'Hasher' module. Get it using 'getHasher'
+-- ------------------------------------------------------------------------------
+--  numBind | Number of bound variables defined by search length and prefix size
+-- ------------------------------------------------------------------------------
+--   runPar | A partially applied function for parallel execution
+-- ------------------------------------------------------------------------------
+-- prefixes | All possible combinations of given prefix characters.
+--          | The search space is equally partioned based on these prefixes.
+--          | length of prefixes == number of sparks
+-- ------------------------------------------------------------------------------
+-- @
+--
 bruteforce :: Int -> String -> String -> Hasher -> Maybe String
 bruteforce size chars hex hasher = found
  where
@@ -36,27 +72,43 @@
   prefixes = bytePrefixes numPrefix chars
 
 -- | Pick up an appropriate search function
+--
+-- Returns a partial application corresponding to the given numBind
+--
 bruteforcePar
-  :: Int
-  -> [C.ByteString]
-  -> C.ByteString
-  -> Hasher
-  -> C.ByteString
-  -> Maybe String
-bruteforcePar n
-  | n `elem` [0 .. defNumBind] = $( funcList ) !! n
+  :: Int -> [ByteString] -> ByteString -> Hasher -> ByteString -> Maybe String
+bruteforcePar numBind
+  | numBind `elem` [0 .. maxNumBind] = $( funcList ) !! numBind
   | otherwise = errorWithoutStackTrace "Not available search length"
 
 -- | Deep Brute-force search including less than a given search size
+--
+-- See the 'bruteforce' function for the arguments used
+--
 bruteforceDeep :: Int -> String -> String -> Hasher -> Maybe String
-bruteforceDeep size x y z = foldl' (<|>) empty found
+bruteforceDeep size chars hex hasher = foldl' (<|>) empty found
  where
-  found = deep x y z <%> [1 .. size]
+  found = deep chars hex hasher <%> [1 .. size]
   deep a b c d = bruteforce d a b c
 
 -- | Parallel map using deepseq, par and pseq
+--
+-- Type of any argument in this map should be instance of 'NFData'.
+--
 (<%>) :: (NFData a, NFData b) => (a -> b) -> [a] -> [b]
 f <%> []       = []
 f <%> (x : xs) = y `par` ys `pseq` (y : ys) where
   y  = force $ f x
   ys = f <%> xs
+
+-- | Image bytestring: target hash value to find
+image :: String -> ByteString
+image = fst . H.decode . C.pack
+
+-- | Bytestring usable for preimage
+byteChars :: String -> [ByteString]
+byteChars chars = C.pack . (: []) <$> chars
+
+-- | Combination of prefixes possible: size of @(length of chars) ^ (numPrefix)@
+bytePrefixes :: Int -> String -> [ByteString]
+bytePrefixes numPrefix chars = C.pack <$> replicateM numPrefix chars
diff --git a/src/Crypto/Longshot/TH.hs b/src/Crypto/Longshot/TH.hs
--- a/src/Crypto/Longshot/TH.hs
+++ b/src/Crypto/Longshot/TH.hs
@@ -7,31 +7,28 @@
 --
 module Crypto.Longshot.TH where
 
-import           Control.Monad
-import           Data.Foldable
+import           Control.Monad                  ( replicateM )
+import           Data.Foldable                  ( foldl' )
+import           Data.ByteString.Char8          ( unpack )
 import           Language.Haskell.TH
-import           Crypto.Longshot
+import           Crypto.Longshot.Const
 
 -- | Brute-force with N-search-length using TH
 bruteforceN :: Int -> Q Exp -> Q Exp -> Q Exp -> Q Exp -> Q Exp
 bruteforceN numBind chars hex hasher prefix = do
   names <- replicateM numBind (newName "names")
   let pats  = varP <$> names
-  let bytes = [| $( prefix ) <>
-                 $( foldl' (\a b -> [| $a <> $b |])
-                    [| mempty |]
-                    (varE <$> names)
-                  )
-              |]
-  let cond  = condE [| $( appE hasher bytes ) == $(hex) |]
-                    [| Just (toKey $( bytes )) |]
+  let bytes = prefix : (varE <$> names)
+  let preimage = [| $( foldl' (\a b -> [| $a <> $b |]) [| mempty |] bytes ) |]
+  let cond  = condE [| $( appE hasher preimage ) == $( hex ) |]
+                    [| Just (unpack $( preimage )) |]
                     [| Nothing |]
   let stmts = ((`bindS` chars) <$> pats) <> [noBindS cond]
   [| foldl' (<|>) empty $( compE stmts ) |]
 
 -- | Declare functions to run in parallel for search
 funcGenerator :: Q [Dec]
-funcGenerator = forM [0 .. defNumBind] funcG where 
+funcGenerator = mapM funcG [0 .. maxNumBind] where
   funcG numBind = do
     let name = mkName $ "bruteforce" <> show numBind
     chars <- newName "chars"
@@ -46,4 +43,4 @@
 
 -- | Get list of functions to run in parallel for search
 funcList :: Q Exp
-funcList = listE (varE . mkName . ("bruteforce" <>) . show <$> [0 .. defNumBind])
+funcList = listE (varE . mkName . ("bruteforce" <>) . show <$> [0 .. maxNumBind])
