diff --git a/Alea/Diceware.hs b/Alea/Diceware.hs
deleted file mode 100644
--- a/Alea/Diceware.hs
+++ /dev/null
@@ -1,28 +0,0 @@
-module Alea.Diceware where
-
-import Data.List  (intersect, elemIndex)
-import Alea.List
-
--- Diceware dictionary type
-type Diceware = [String]
-
--- Parse file content to a Diceware
-parseDiceware :: String -> Diceware
-parseDiceware x = map (last . split ' ') $ lines x
-
--- 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
-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]
diff --git a/Alea/List.hs b/Alea/List.hs
deleted file mode 100644
--- a/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/Alea/Random.hs b/Alea/Random.hs
deleted file mode 100644
--- a/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 = newSkeinGen >>= return . take k . randomRs (0, n-1)
diff --git a/Main.hs b/Main.hs
deleted file mode 100644
--- a/Main.hs
+++ /dev/null
@@ -1,56 +0,0 @@
-{-# LANGUAGE RecordWildCards #-}
-
-import System.IO
-import System.Console.ArgParser
-import Control.Monad
-import Control.Applicative
-
-import Paths_alea (getDataFileName)
-import Alea.Diceware
-import Alea.Random
-
-data ProgArgs = ProgArgs
-	{ interactive  :: Bool
-	, dictionary   :: FilePath
-	, phraseLength :: Int
-	, phrases      :: Int
-	} deriving (Show)
-
-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)
-
-main :: IO ()
-main = interface >>= flip runApp (readDict >=> exec)
-
--- 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
-
--- 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
diff --git a/alea.cabal b/alea.cabal
--- a/alea.cabal
+++ b/alea.cabal
@@ -1,5 +1,5 @@
 name:                alea
-version:             0.3.2.0
+version:             0.3.3.0
 synopsis:            a diceware passphrase generator
 description:
 
@@ -25,6 +25,7 @@
 
 executable alea
   main-is:             Main.hs
+  hs-source-dirs:      src
   default-language:    Haskell2010
   other-modules:       Alea.Diceware, Alea.List, Alea.Random, Paths_alea
   other-extensions:    DeriveDataTypeable, RecordWildCards
diff --git a/src/Alea/Diceware.hs b/src/Alea/Diceware.hs
new file mode 100644
--- /dev/null
+++ b/src/Alea/Diceware.hs
@@ -0,0 +1,28 @@
+module Alea.Diceware where
+
+import Data.List  (intersect, elemIndex)
+import Alea.List
+
+-- Diceware dictionary type
+type Diceware = [String]
+
+-- Parse file content to a Diceware
+parseDiceware :: String -> Diceware
+parseDiceware x = map (last . split ' ') $ lines x
+
+-- 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
+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]
diff --git a/src/Alea/List.hs b/src/Alea/List.hs
new file mode 100644
--- /dev/null
+++ b/src/Alea/List.hs
@@ -0,0 +1,10 @@
+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
new file mode 100644
--- /dev/null
+++ b/src/Alea/Random.hs
@@ -0,0 +1,6 @@
+module Alea.Random where
+
+import Crypto.Threefish.Random
+
+randWords :: Int -> Int -> IO [Int]
+randWords n k = newSkeinGen >>= return . take k . randomRs (0, n-1)
diff --git a/src/Main.hs b/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Main.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE RecordWildCards #-}
+
+import System.IO
+import System.Console.ArgParser
+import Control.Monad
+import Control.Applicative
+
+import Paths_alea (getDataFileName)
+import Alea.Diceware
+import Alea.Random
+
+data ProgArgs = ProgArgs
+	{ interactive  :: Bool
+	, dictionary   :: FilePath
+	, phraseLength :: Int
+	, phrases      :: Int
+	} deriving (Show)
+
+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)
+
+main :: IO ()
+main = interface >>= flip runApp (readDict >=> exec)
+
+-- 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
+
+-- 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
