diff --git a/alea.cabal b/alea.cabal
--- a/alea.cabal
+++ b/alea.cabal
@@ -1,5 +1,5 @@
 name:                alea
-version:             0.4.0.0
+version:             0.5.0.0
 synopsis:            a diceware passphrase generator
 description:
 
@@ -10,7 +10,7 @@
 homepage:            https://github.com/Rnhmjoj/alea
 license:             MIT
 license-file:        LICENSE
-author:              Rnhmjoj
+author:              rnhmjoj
 maintainer:          micheleguerinirocco@me.com
 copyright:           (C) Michele Guerini Rocco 2015
 category:            Utility
@@ -27,8 +27,8 @@
   main-is:             Main.hs
   hs-source-dirs:      src
   default-language:    Haskell2010
-  other-modules:       Alea.Diceware, Alea.List, Alea.Random
+  other-modules:       Alea.Diceware
   other-extensions:    DeriveDataTypeable, RecordWildCards
-  build-depends:       base >=4.8 && < 5.0, containers,
-                       argparser, threefish
+  build-depends:       base >=4.8 && < 5.0, random, text,
+                       optparse-applicative 
   ghc-options:         -O2
diff --git a/src/Alea/Diceware.hs b/src/Alea/Diceware.hs
--- a/src/Alea/Diceware.hs
+++ b/src/Alea/Diceware.hs
@@ -1,28 +1,42 @@
+{-# LANGUAGE OverloadedStrings #-}
+
 module Alea.Diceware where
 
-import Data.List  (intersect, elemIndex)
-import Alea.List
+import Data.Monoid   ((<>))
+import Data.List     (intersect, elemIndex)
+import Data.Text     (Text, pack)
+import System.Random
+import qualified Data.Text as T
 
--- Diceware dictionary type
-type Diceware = [String]
 
--- Parse file content to a Diceware
-parseDiceware :: String -> Diceware
-parseDiceware x = map (last . split ' ') $ lines x
+-- | Diceware dictionary alias
+type Diceware = [Text]
 
--- Lookup word with dice index
-readDiceware :: Diceware -> Int -> String
-readDiceware d n = show n ++ " -> " ++
-  case (undice n) of
-    Just x -> d !! x
-    Nothing -> "Does not exist"
 
--- Lookup word with linear index
-readDiceware' :: Diceware -> Int -> String
+-- | Produces k random indices to be extracted
+randIndices :: Int -> Int -> IO [Int]
+randIndices n k = take k <$> randomRs (0, n-1) <$> newStdGen
+
+
+-- | Parse file content to a Diceware
+parseDiceware :: Text -> Diceware
+parseDiceware = map (last . T.splitOn " ") . T.lines
+
+
+-- | Lookup word with dice index
+readDiceware :: Diceware -> Int -> Text
+readDiceware d n =
+  pack (show n) <> " -> " <>
+  maybe "Does not exists" (d !!) (fromDice n)
+
+
+-- | Lookup word with linear index
+readDiceware' :: Diceware -> Int -> Text
 readDiceware' d n = d !! n
 
--- Dice numbers to numbers
--- Ex. undice 11121 == Just 6
-undice :: Int -> Maybe Int
-undice n = elemIndex n . filter
-  (null . (intersect "0789") . show) $ [11111..66666]
+
+-- | Dice numbers to numbers
+-- > fromDice 11121 == Just 6
+fromDice :: Int -> Maybe Int
+fromDice n = elemIndex n (filter isDice [11111..66666])
+  where isDice = null . (intersect "0789") . show
diff --git a/src/Alea/List.hs b/src/Alea/List.hs
deleted file mode 100644
--- a/src/Alea/List.hs
+++ /dev/null
@@ -1,10 +0,0 @@
-module Alea.List where
-
--- Split a list into a list of lists
--- ex. split ',' "ab,cd,ef" == ["ab","cd","ef"]
-split :: (Eq a) => a -> [a] -> [[a]]
-split _ [] = [[]]
-split delim (c:cs)
-  | c == delim = [] : rest
-  | otherwise = (c : head rest) : tail rest
-  where rest = split delim cs
diff --git a/src/Alea/Random.hs b/src/Alea/Random.hs
deleted file mode 100644
--- a/src/Alea/Random.hs
+++ /dev/null
@@ -1,6 +0,0 @@
-module Alea.Random where
-
-import Crypto.Threefish.Random
-
-randWords :: Int -> Int -> IO [Int]
-randWords n k = take k . randomRs (0, n-1) <$> newSkeinGen
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -1,55 +1,79 @@
 {-# LANGUAGE RecordWildCards #-}
 
-import System.IO
-import System.Console.ArgParser
-import Control.Monad
-
-import Paths_alea (getDataFileName)
+import Control.Monad             (when, forever)
+import Data.Text                 (unpack)
+import Options.Applicative
 import Alea.Diceware
-import Alea.Random
+import Paths_alea                (getDataFileName)
 
-data ProgArgs = ProgArgs
-	{ interactive  :: Bool
-	, dictionary   :: FilePath
-	, phraseLength :: Int
-	, phrases      :: Int
-	} deriving (Show)
+import qualified Data.Text    as T
+import qualified Data.Text.IO as I
 
-parser :: IO (ParserSpec ProgArgs)
-parser = (\path -> ProgArgs
-  `parsedBy` boolFlag      "interactive" `Descr` "Manually insert numbers"
-  `andBy`    optFlag  path "dictionary"  `Descr` "Specify dictionary file path"
-  `andBy`    optFlag  6    "lenght"      `Descr` "Number of words in a passphrase"
-  `andBy`    optFlag  1    "phrases"     `Descr` "Number of passphrases to generate")
-  <$> path
 
-interface :: IO (CmdLnInterface ProgArgs)
-interface =
-  (`setAppDescr` "A diceware passphrase generator") <$>
-  (`setAppEpilog` "Alea iacta est.") <$>
-  (mkApp =<< parser)
+-- * Command line interface description
 
+-- | Program arguments record
+data Options = Options
+  { interactive  :: Bool
+  , dictionary   :: Maybe FilePath
+  , phraseLength :: Int
+  , phrases      :: Int
+  }
+
+
+-- | Argument parser 
+options :: Parser Options
+options = Options 
+  <$> switch
+      ( long "interactive"
+     <> help "Manually insert numbers from a dice" )
+  <*> optional (option auto
+      ( long "dictionary"
+     <> metavar "FILEPATH"
+     <> help "Specify dictionary filepath" ))
+  <*> option auto
+      ( long "length"
+     <> value 6
+     <> metavar "N"
+     <> help "Number of words in a passphrase")
+  <*> option auto
+     ( long "phrases"
+    <> value 1
+    <> metavar "M"
+    <> help "Number of passphrases to generate" )
+  
+
+-- | Program description
+description :: ParserInfo Options
+description = info (helper <*> options)
+  ( fullDesc
+ <> progDesc "A diceware passphrase generator"
+ <> footer "Alea iacta est." )
+
+
+
+-- * Program
+
+-- | Main function
 main :: IO ()
-main = interface >>= flip runApp (readDict >=> exec)
+main = execParser description >>= diceware
 
--- Default path of the dictionary
-path :: IO FilePath
-path = getDataFileName "dict/diceware"
 
--- Read dictionary file
-readDict :: ProgArgs -> IO ProgArgs
-readDict args@ProgArgs{..} =
-  (\x -> args {dictionary = x}) <$> readFile dictionary
+-- | Actual application 
+diceware :: Options -> IO ()
+diceware opts@Options{..} = do
+  path <- case dictionary of
+    Nothing -> getDataFileName "dict/diceware"
+    Just x  -> return x
+  dict <- parseDiceware <$> I.readFile path
+  let size  = length dict-1
+      dice  = readDiceware  dict . read . unpack
+      dice' = readDiceware' dict
 
--- Main function
-exec :: ProgArgs -> IO ()
-exec args@ProgArgs{..} =
-	if interactive
-	  then interact (unlines . map dice . lines)
-	  else do
-	    randWords dictSize phraseLength >>= putStrLn . unwords . map dice'
-	    when (phrases > 1) $ exec args {phrases = phrases - 1}
-	where
-	  (dict, dictSize) = (parseDiceware dictionary, length dict)
-	  dice  n = readDiceware  dict (read n :: Int)
-	  dice' n = readDiceware' dict n
+  if interactive
+    then forever (dice <$> I.getLine >>= I.putStrLn)
+    else do
+      indices <- randIndices size phraseLength
+      I.putStrLn $ T.unwords (map dice' indices)
+      when (phrases > 1) $
+        diceware opts {phrases = phrases - 1}
