diff --git a/Development/Hake.cpphs b/Development/Hake.cpphs
deleted file mode 100644
--- a/Development/Hake.cpphs
+++ /dev/null
@@ -1,188 +0,0 @@
-module Development.Hake (
-  Rule
-, hake
-, hakeT
-, hakefileIs
-
-, file
-, task
-, rule
-, ruleSS
-, dflt
-, mkfl
-
-, lift
-, systemE
-, getSrcs
-, isSuffixOf
-, changeSuffix
-, ExitCode(ExitSuccess)
-) where
-
-import System.Environment           (getArgs)
-import Data.List                    (isSuffixOf)
-import System.Exit                  (ExitCode(ExitSuccess), exitWith)
-import System.Cmd                   (system)
-import System.Directory             (doesFileExist)
-import Control.Applicative          ((<$>))
-import Development.Hake.HiddenTools (isOldThanSomeOf, runHake, hakefileUpdateOption)
-import Control.Monad.Reader         (asks, ReaderT(runReaderT), lift)
-#ifdef DEBUG
-import Control.Monad.Reader         (ask)
-#endif /* DEBUG */
-import Control.Monad.Utils          (ifM, whenM)
-import System.IO.Unsafe             (unsafeInterleaveIO
-#ifdef DEBUG
-                                     , unsafePerformIO
-#endif /* DEBUG */
-                                     )
-
-type Targets   = [ String -> Bool ]
-type Sources   = String -> SourcesRet
-type Commands  = String -> [ String ] -> [ CommandRet ]
-type Rule      = ( Targets, Sources, Commands )
-type RuleInner = ( Targets, (Sources, Commands) )
-
-type TargetRet   = String
-type SourcesRet  = [ String ]
-type CommandIO   = ReaderT (Bool, MadeFromList) IO
-type CommandRet  = CommandIO ExitCode
-type RuleRet     = ( TargetRet, (SourcesRet, [CommandRet]) )
-
-type MadeFromList = [ (FilePath, [FilePath]) ]
-
-ruleToRuleInner :: Rule -> RuleInner
-ruleToRuleInner ( x, y, z ) = ( x, (y, z) )
-
-ruleRetToMadeFromList :: [ RuleRet ] -> MadeFromList
-ruleRetToMadeFromList = map (\(x, (y, _)) -> (x, y))
-
-hake :: [ Rule ] -> IO ()
-hake rl = do args <- getArgs
-             let ud    = elem hakefileUpdateOption args
-	         args_ = filter (/=hakefileUpdateOption) args
-             case args_ of
-	          [ trgt ] -> hakeTarget ud (map ruleToRuleInner rl) trgt
-		  _        -> error "function (hake): argument error"
-
-hakeT :: [ Rule ] -> FilePath -> IO ()
-hakeT = hakeTarget True . map ruleToRuleInner
-
-hakeTarget :: Bool -> [ RuleInner ] -> FilePath -> IO ()
-hakeTarget ud rls fn = do
-  rl <- traceRule fn rls
-#ifdef DEBUG
---          >>= return . d (map $ map st)
---  print $ map (map st) rl
-#endif /* DEBUG */
-  flip runReaderT (ud, ruleRetToMadeFromList $ head rl) $ mapM_ applyRule $ reverse $ head rl
-
-#ifdef DEBUG
-d :: Show b => (a -> b) -> a -> a
-d f x = unsafePerformIO $ print (f x) >> return x
-st :: RuleRet -> (TargetRet, SourcesRet)
-st (t, (s, _)) = (t, s)
-#endif /* DEBUG */
-
-infixr 9 <.>
-(<.>) :: Functor f => (a -> b) -> (c -> f a) -> c -> f b
-f1 <.> f2 = fmap f1 . f2
-
-traceRule :: FilePath -> [ RuleInner ] -> IO [[ RuleRet ]]
-traceRule trgt rls
-  =
-#ifdef DEBUG
- do putStrLn $ "traceRule " ++ show trgt ++ " rls"
-#endif /* DEBUG */
-    case myLookup trgt rls of
-      []    ->
-#ifdef DEBUG
-            do exStat <- ifM (doesFileExist trgt) (return " exist") (return " does not exist")
-	       putStrLn $ "DEBUG (traceRule) : target " ++ trgt ++ exStat
-#endif /* DEBUG */
-               ifM (doesFileExist trgt) (return [[]]) (return [])
-      finds -> do
-        optional <- ifM (doesFileExist trgt) (return [[]]) (return [])
-        fmap (++optional) $ concat <.> flip mapM finds $ \((tToS, tsToCmds), restRls) -> do
-          let srcs = tToS trgt
-	      cmds = tsToCmds trgt srcs
-          obtainedRls <- mapM (unsafeInterleaveIO . flip traceRule restRls) srcs
-	  return $ map ( (( trgt, (srcs, cmds) ):) . concat ) $ mulLists obtainedRls
-
-mulLists :: [[a]] -> [[a]]
-mulLists [] = [[]]
-mulLists (xs:xss) = [ x:xs_ | x <- xs, xs_ <- mulLists xss ]
-
-applyRule :: (TargetRet, (SourcesRet, [CommandRet])) -> CommandRet
-applyRule (src, (dsts, cmds))
-  = ifM ( lift $ isOldThanSomeOf src dsts )
-        ( abortIfFailure cmds )
-        ( return ExitSuccess )
-
-myLookup :: a -> [ ([a -> Bool], b) ] -> [ (b, [ ([a -> Bool], b) ]) ]
-myLookup _ []            = []
-myLookup x (pair@(p, y):rest)
-  | or $ map ($x) p
-    = (y, rest) : ( (\(z, ps) -> (z, pair:ps)) <$> myLookup x rest )
-  | otherwise
-    =               (\(z, ps) -> (z, pair:ps)) <$> myLookup x rest
-
-changeSuffix :: String -> String -> String -> String
-changeSuffix oldSfx newSfx fn
-  | isSuffixOf oldSfx fn = take (length fn - length oldSfx) fn ++ newSfx
-  | otherwise            = error $ "changeSuffix: " ++ oldSfx ++ " is not suffix of " ++ fn
-
-const2 :: a -> b -> c -> a
-const2 = const . const
-
-systemE :: String -> CommandRet
-systemE cmd = lift $ putStrLn cmd >> system cmd
-
-dflt :: [ String ] -> Rule
-dflt trgts = ( [ (=="default") ], const trgts, const2 [] )
-
-file :: ( [String], [String], [String] ) -> Rule
-file ( trgts, srcs, cmd ) = ( map (==) trgts, const srcs, const2 $ map systemE cmd )
-
-task :: ( String, [String] ) -> Rule
-task ( trgts, cmd )       = ( [(==trgts)], const [], const2 $ map systemE cmd )
-
-rule :: ( String, String, String -> String -> [String] ) -> Rule
-rule ( trgt, src, cmd )
-  = ( [isSuffixOf trgt], \dst -> [changeSuffix trgt src dst ],
-      \t [s] -> map systemE $ cmd t s )
-
-ruleSS :: ( String, String, String -> String -> [ (String, [String]) ] ) -> Rule
-ruleSS ( trgt, src, cmds )
-  = ( [ isSuffixOf trgt ], \dst -> [ changeSuffix trgt src dst ],
-        \t [s] -> [ do [ srcSrc ] <- getSrcs s
-	               abortIfFailure $ map systemE $
-		         snd $ head $ filter ( flip isSuffixOf srcSrc . fst ) $ cmds t s ] )
-
-abortIfFailure :: [ CommandRet ] -> CommandRet
-abortIfFailure = last <.> mapM (>>= (\ec -> if ec == ExitSuccess then return ec else lift $ exitWith ec)) 
-
-mkfl :: ( String, [ String ] ) -> Rule
-mkfl ( trgt, cont )
-  = ( [(==trgt)], const [], \t -> const [ do
-        whenM getUpdateStatus $ do lift $ putStrLn $ "make file `" ++ trgt ++ "' (hake)"
-	                           lift $ writeFile t $ unlines cont
-	return ExitSuccess ] )
-
-{-
-mkfl2 :: ( String, [ String ], [ String ] -> IO [ String ] ) -> Rule
-mkfl2 ( trgt, src, cont )
-  = ( [(==trgt)], const src, \t -> const [ do
-        whenM getUpdateStatus $ 
-	-}
-
-hakefileIs :: FilePath -> [ FilePath ] -> IO ExitCode
-hakefileIs src others = do
-  args <- getArgs
-  runHake src "hake_" others $ if null args then [ "default" ] else args
-
-getUpdateStatus :: CommandIO Bool
-getUpdateStatus = asks fst
-
-getSrcs :: FilePath -> CommandIO [FilePath]
-getSrcs fp = asks (maybe [] id . lookup fp . snd)
diff --git a/Development/Hake.hs b/Development/Hake.hs
new file mode 100644
--- /dev/null
+++ b/Development/Hake.hs
@@ -0,0 +1,171 @@
+{- hake: make tool. ruby : rake = haskell : hake
+Copyright (C) 2008-2008 Yoshikuni Jujo <PAF01143@nifty.ne.jp>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+
+module Development.Hake (
+  Rule
+, hake
+, hakeT
+, hakefileIs
+
+, file
+, task
+, rule
+, ruleSS
+, dflt
+, mkfl
+
+, liftIO
+, systemE
+, getSrcs
+, isSuffixOf
+, changeSuffix
+, ExitCode(ExitSuccess)
+) where
+
+import System.Environment           (getArgs)
+import System.Exit                  (ExitCode(ExitSuccess), exitWith)
+import System.Cmd                   (system)
+import System.Directory             (doesFileExist)
+import System.IO.Unsafe             (unsafeInterleaveIO)
+import Control.Monad.Reader         (asks, ReaderT(runReaderT), lift, liftIO)
+import Control.Monad.Utils          (ifM, whenM)
+import Control.Applicative          ((<$>))
+import Control.Applicative.Utils    ((<.>))
+import Data.List                    (isSuffixOf)
+import Data.List.Tools              (mulLists)
+import Data.Tuple.Tools             (modifySnd)
+import Data.Function.Tools          (const2)
+import Development.Hake.HiddenTools (isOldThanSomeOf, runHake, hakefileUpdateOption, defaultTrgtStr)
+
+type Targets   = [ String -> Bool ]
+type Sources   = String -> SourcesRet
+type Commands  = String -> [ String ] -> [ CommandRet ]
+type Rule      = ( Targets, Sources, Commands )
+type RuleInner = ( Targets, (Sources, Commands) )
+
+type TargetRet   = String
+type SourcesRet  = [ String ]
+type CommandIO   = ReaderT (Bool, MadeFromList) IO
+type CommandRet  = CommandIO ExitCode
+type RuleRet     = ( TargetRet, (SourcesRet, [CommandRet]) )
+
+type MadeFromList = [ (FilePath, [FilePath]) ]
+
+ruleToRuleInner :: Rule -> RuleInner
+ruleToRuleInner ( x, y, z ) = ( x, (y, z) )
+
+ruleRetToMadeFromList :: [ RuleRet ] -> MadeFromList
+ruleRetToMadeFromList = map (\(x, (y, _)) -> (x, y))
+
+-- |The 'hake' function take rules as argument and get target from command line and make target.
+hake :: [ Rule ] -> IO ()
+hake rl = do args <- getArgs
+             let ud    = elem hakefileUpdateOption args
+	         args_ = filter (/=hakefileUpdateOption) args
+             case args_ of
+	          [ trgt ] -> hakeTarget ud (map ruleToRuleInner rl) trgt
+		  _        -> error "function (hake): argument error"
+
+hakeT :: [ Rule ] -> FilePath -> IO ()
+hakeT = hakeTarget True . map ruleToRuleInner
+
+hakeTarget :: Bool -> [ RuleInner ] -> FilePath -> IO ()
+hakeTarget ud rls fn = do
+  rrls <- traceRule fn rls
+  case rrls of
+       []  -> error $ "No usable rules for make target '" ++ fn ++ "'"
+       r:_ -> flip runReaderT (ud, ruleRetToMadeFromList r) $ mapM_ applyRule $ reverse r
+
+traceRule :: FilePath -> [ RuleInner ] -> IO [[ RuleRet ]]
+traceRule trgt rls
+  = case myLookup trgt rls of
+      []    -> ifM (doesFileExist trgt) (return [[]]) (return [])
+      finds -> do
+        optional <- ifM (doesFileExist trgt) (return [[]]) (return [])
+        fmap (++optional) $ concat <.> flip mapM finds $ \((tToS, tsToCmds), restRls) -> do
+          let srcs = tToS trgt
+	      cmds = tsToCmds trgt srcs
+          obtainedRls <- mapM (unsafeInterleaveIO . flip traceRule restRls) srcs
+	  return $ map ( (( trgt, (srcs, cmds) ):) . concat ) $ mulLists obtainedRls
+
+applyRule :: (TargetRet, (SourcesRet, [CommandRet])) -> CommandRet
+applyRule (src, (dsts, cmds))
+  = ifM ( lift $ isOldThanSomeOf src dsts )
+        ( abortIfFailure cmds )
+        ( return ExitSuccess )
+
+myLookup :: a -> [ ([a -> Bool], b) ] -> [ (b, [ ([a -> Bool], b) ]) ]
+myLookup _ []            = []
+myLookup x (pair@(p, y):rest)
+  | or $ map ($x) p
+    = (y, rest) : ( modifySnd (pair:) <$> myLookup x rest )
+  | otherwise
+    =               modifySnd (pair:) <$> myLookup x rest
+
+changeSuffix :: String -> String -> String -> String
+changeSuffix oldSfx newSfx fn
+  | isSuffixOf oldSfx fn = take (length fn - length oldSfx) fn ++ newSfx
+  | otherwise            = error $ "changeSuffix: " ++ oldSfx ++ " is not suffix of " ++ fn
+
+systemE :: String -> CommandRet
+systemE cmd = lift $ putStrLn cmd >> system cmd
+
+dflt :: [ String ] -> Rule
+dflt trgts = ( [ (==defaultTrgtStr) ], const trgts, const2 [] )
+
+file :: ( [String], [String], [String] ) -> Rule
+file ( trgts, srcs, cmd ) = ( map (==) trgts, const srcs, const2 $ map systemE cmd )
+
+task :: ( String, [String] ) -> Rule
+task ( trgts, cmd )       = ( [(==trgts)], const [], const2 $ map systemE cmd )
+
+rule :: ( String, String, String -> String -> [String] ) -> Rule
+rule ( trgt, src, cmd )
+  = ( [isSuffixOf trgt], \dst -> [changeSuffix trgt src dst ],
+      \t [s] -> map systemE $ cmd t s )
+
+ruleSS :: ( String, String, String -> String -> [ (String, [String]) ] ) -> Rule
+ruleSS ( trgt, src, cmds )
+  = ( [ isSuffixOf trgt ], \dst -> [ changeSuffix trgt src dst ],
+        \t [s] -> [ do [ srcSrc ] <- getSrcs s
+	               abortIfFailure $ map systemE $
+		         snd $ head $ filter ( flip isSuffixOf srcSrc . fst ) $ cmds t s ] )
+
+abortIfFailure :: [ CommandRet ] -> CommandRet
+abortIfFailure = (<.>) last $ mapM $ flip (>>=) $ \ec ->
+  case ec of
+       ExitSuccess -> return ec
+       _           -> lift $ exitWith ec
+
+mkfl :: ( String, [ String ] ) -> Rule
+mkfl ( trgt, cont )
+  = ( [ (==trgt) ], const [], \t -> const [ do
+        whenM getUpdateStatus $ do
+	  lift $ putStrLn $ "make file `" ++ trgt ++ "' (hake)"
+	  lift $ writeFile t $ unlines cont
+	return ExitSuccess ] )
+
+hakefileIs :: FilePath -> [ FilePath ] -> IO ExitCode
+hakefileIs src others = do
+  args <- getArgs
+  runHake src "hake_" others $ if null args then [ defaultTrgtStr ] else args
+
+getUpdateStatus :: CommandIO Bool
+getUpdateStatus = asks fst
+
+getSrcs :: FilePath -> CommandIO [FilePath]
+getSrcs fp = asks (maybe [] id . lookup fp . snd)
diff --git a/Development/Hake/HiddenTools.cpphs b/Development/Hake/HiddenTools.cpphs
--- a/Development/Hake/HiddenTools.cpphs
+++ b/Development/Hake/HiddenTools.cpphs
@@ -1,13 +1,31 @@
+{- hake: make tool. ruby : rake = haskell : hake
+Copyright (C) 2008-2008 Yoshikuni Jujo <PAF01143@nifty.ne.jp>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+
 module Development.Hake.HiddenTools (
   runHake
 , isOldThanSomeOf
 , hakefileUpdateOption
+, defaultTrgtStr
 ) where
 
 import System.Directory     (createDirectory, doesDirectoryExist,
                              doesFileExist, copyFile, getModificationTime)
 import System.Process       (runProcess, waitForProcess)
-import System.Exit          (ExitCode)
+import System.Exit          (ExitCode(ExitSuccess))
 import System.Time          (ClockTime)
 import System.IO            (openFile, hClose, IOMode(WriteMode))
 import Control.Applicative  ((<$>), liftA2)
@@ -45,7 +63,7 @@
   when hakefileUD $
     readFile src >>= writeFile ("_hake/" ++ exe ++ ".hs")
 #ifndef DEBUG
-  bracket (flip openFile WriteMode $ "_hake/" ++ exe ++ ".error") hClose $ \errH ->
+  ret <- bracket (flip openFile WriteMode $ "_hake/" ++ exe ++ ".error") hClose $ \errH ->
     let mErrH = Just errH in
 #else
   let mErrH = Nothing in
@@ -53,8 +71,14 @@
       runProcess "ghc" [ "--make", exe ] (Just "_hake")
                  Nothing Nothing Nothing mErrH >>= waitForProcess
   let args_ = if othrsUD || hakefileUD then (hakefileUpdateOption:args) else args
+  case ret of
+       ExitSuccess -> return ()
+       _           -> readFile ("_hake/" ++ exe ++ ".error") >>= putStr
   runProcess ("_hake/" ++ exe) (if null args then ("default":args_) else args_)
              Nothing Nothing Nothing Nothing Nothing >>= waitForProcess
 
 basename :: FilePath -> FilePath
 basename = reverse . takeWhile (/='/') . reverse
+
+defaultTrgtStr :: String
+defaultTrgtStr = "default"
diff --git a/Main.hs b/Main.hs
--- a/Main.hs
+++ b/Main.hs
@@ -1,13 +1,33 @@
+{- hake: make tool. ruby : rake = haskell : hake
+Copyright (C) 2008-2008 Yoshikuni Jujo <PAF01143@nifty.ne.jp>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+
 module Main where
 
 import System.Environment           (getArgs)
 import System.Exit                  (ExitCode(ExitSuccess))
-import Development.Hake.HiddenTools (runHake)
+import Development.Hake.HiddenTools (runHake, defaultTrgtStr)
 import Paths_hake                   (version)
 import Data.Version                 (showVersion)
 
 main :: IO ExitCode
-main = do args <- getArgs
-          case args of
-	    [ "--version" ] -> putStrLn ("hake " ++ showVersion version) >> return ExitSuccess
-            _               -> runHake "Hakefile" "hake" [] (if null args then ["default"] else args)
+main = do
+  args <- getArgs
+  case args of
+       [ "--version" ] ->
+	 putStrLn ("hake " ++ showVersion version) >> return ExitSuccess
+       _               ->
+	 runHake "Hakefile" "hake" [] (if null args then [defaultTrgtStr] else args)
diff --git a/hake.cabal b/hake.cabal
--- a/hake.cabal
+++ b/hake.cabal
@@ -1,11 +1,11 @@
 Name:		hake
-Version:	0.3
+Version:	0.4
 License:	GPL
 License-file:	LICENSE
 Author:		Yoshikuni Jujo
 Maintainer:	Yoshikuni Jujo <PAF01143@nifty.ne.jp>
 Category:	Development
-Synopsis:	ruby : rake = haskell : hake
+Synopsis:	make tool. ruby : rake = haskell : hake
 
 Description:	Like ruby's rake, hake have Hakefile which is Haskell source.
 		.
@@ -45,16 +45,17 @@
 		>  rule   ( ".o", ".cc", \_ s -> [ "g++ -c " ++ s ] )
 		>  ,
 		>  ( [ (=="foo") ], const [ "foo.gen", "Hakefile" ], \t [s] -> [ do
-		>         gen <- readFile s
-		>         writeFile t $ unlines $ [ "#!/bin/sh", "echo This is script" ] ++ lines gen ] )
+		>         gen <- liftIO $ readFile s
+		>         liftIO $ writeFile t $ unlines $
+		>           [ "#!/bin/sh", "echo This is script" ] ++ lines gen ] )
 		>
 		>  ]
 		>
-		> main = hake hake_tree
+		> main = hake hake_rules
 
 Stability:	experimental
 Homepage:	http://homepage3.nifty.com/salamander/second/projects/hake/index.xhtml
-Package-Url:	http://homepage3.nifty.com/salamander/second/portage/distfiles/hake-0.2.tar.gz
+Package-Url:	http://homepage3.nifty.com/salamander/second/portage/distfiles/hake-0.4.tar.gz
 Cabal-Version:	>= 1.2
 Build-type:	Simple
 Tested-With:	GHC
@@ -72,6 +73,6 @@
 Executable hake
   GHC-Options:		-Wall
 --  CPP-Options:		-DDEBUG
-  Build-Depends:	directory, process, yjtools
+  Build-Depends:	directory, process, yjtools > 0.1
   Other-Modules:	Development.Hake.HiddenTools
   Main-Is:		Main.hs
