diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/simple-log.cabal b/simple-log.cabal
--- a/simple-log.cabal
+++ b/simple-log.cabal
@@ -1,5 +1,5 @@
 Name:                 simple-log
-Version:              0.9.3
+Version:              0.9.4
 Synopsis:             Simple log for Haskell
 Description:          Log library for Haskell
 License:              BSD3
@@ -60,6 +60,6 @@
   build-depends:
     base >= 4.0 && < 6,
     simple-log,
-    hspec >= 2.3 && < 2.5,
+    hspec >= 2.3 && < 2.6,
     microlens-platform == 0.3.*,
     text >= 0.11.0 && < 2.0.0
diff --git a/src/System/Log/Simple/Base.hs b/src/System/Log/Simple/Base.hs
--- a/src/System/Log/Simple/Base.hs
+++ b/src/System/Log/Simple/Base.hs
@@ -26,6 +26,7 @@
 import Data.Map (Map)
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe)
+import Data.Semigroup (Semigroup(..))
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.Time
@@ -73,6 +74,9 @@
 instance IsString Component where
 	fromString = read
 
+instance Semigroup Component where
+	Component l <> Component r = Component $ r ++ l
+
 instance Monoid Component where
 	mempty = Component []
 	Component l `mappend` Component r = Component $ r ++ l
@@ -93,6 +97,9 @@
 
 instance IsString Scope where
 	fromString = read
+
+instance Semigroup Scope where
+	Scope l <> Scope r = Scope $ r ++ l
 
 instance Monoid Scope where
 	mempty = Scope []
diff --git a/src/System/Log/Simple/Stream.hs b/src/System/Log/Simple/Stream.hs
--- a/src/System/Log/Simple/Stream.hs
+++ b/src/System/Log/Simple/Stream.hs
@@ -1,28 +1,28 @@
-module System.Log.Simple.Stream (
-	stream, console,
-	coloredStream, coloredConsole
-	) where
-
-import Control.Monad.IO.Class
-import Data.Text (Text)
-import qualified Data.Text.IO as T
-import System.Log.Simple.Base
-import System.IO
-import Text.Format (Formatted)
-import Text.Format.Colored
-
-stream ∷ Handle → Consumer Text
-stream h = do
-	liftIO $ hSetEncoding h utf8
-	return $ \txt → T.hPutStrLn h txt >> hFlush h
-
-console ∷ Consumer Text
-console = stream stderr
-
-coloredStream ∷ Handle → Consumer Formatted
-coloredStream h = do
-	liftIO $ hSetEncoding h utf8
-	return $ \f → hColoredLine h f >> hFlush h
-
-coloredConsole ∷ Consumer Formatted
-coloredConsole = coloredStream stderr
+module System.Log.Simple.Stream (
+	stream, console,
+	coloredStream, coloredConsole
+	) where
+
+import Control.Monad.IO.Class
+import Data.Text (Text)
+import qualified Data.Text.IO as T
+import System.Log.Simple.Base
+import System.IO
+import Text.Format (Formatted)
+import Text.Format.Colored
+
+stream ∷ Handle → Consumer Text
+stream h = do
+	liftIO $ hSetEncoding h utf8
+	return $ \txt → T.hPutStrLn h txt >> hFlush h
+
+console ∷ Consumer Text
+console = stream stderr
+
+coloredStream ∷ Handle → Consumer Formatted
+coloredStream h = do
+	liftIO $ hSetEncoding h utf8
+	return $ \f → hColoredLine h f >> hFlush h
+
+coloredConsole ∷ Consumer Formatted
+coloredConsole = coloredStream stderr
diff --git a/src/System/Log/Simple/Text.hs b/src/System/Log/Simple/Text.hs
--- a/src/System/Log/Simple/Text.hs
+++ b/src/System/Log/Simple/Text.hs
@@ -1,32 +1,32 @@
-module System.Log.Simple.Text (
-	defaultTimeFormat,
-	textFmt, text, shortText, msgOnly
-	) where
-
-import Data.Time
-import Text.Format
-
-import System.Log.Simple.Base
-
--- | Default time format
-defaultTimeFormat ∷ String
-defaultTimeFormat = "%_Y-%m-%d %T %z"
-
-textFmt ∷ FormatResult r ⇒ String → String → Converter r
-textFmt tmFmt msgFmt (Message tm l comp scope msg) = format msgFmt ~~ args where
-	args = [
-		"time" ~% formatTime defaultTimeLocale tmFmt tm,
-		"level" ~% l,
-		"component" ~% comp,
-		"scope" ~% scope,
-		"message" ~% msg]
-
--- | Text log converter with default time format
-text ∷ FormatResult r ⇒ Converter r
-text = textFmt defaultTimeFormat "{time:cyan}\t{level}\t{component:magenta}:{scope:green}> {message}"
-
-shortText ∷ FormatResult r ⇒ Converter r
-shortText = textFmt defaultTimeFormat "{level}\t{component:magenta}: {message}"
-
-msgOnly ∷ FormatResult r ⇒ Converter r
-msgOnly = textFmt defaultTimeFormat "{message}"
+module System.Log.Simple.Text (
+	defaultTimeFormat,
+	textFmt, text, shortText, msgOnly
+	) where
+
+import Data.Time
+import Text.Format
+
+import System.Log.Simple.Base
+
+-- | Default time format
+defaultTimeFormat ∷ String
+defaultTimeFormat = "%_Y-%m-%d %T.%3q %z"
+
+textFmt ∷ FormatResult r ⇒ String → String → Converter r
+textFmt tmFmt msgFmt (Message tm l comp scope msg) = format msgFmt ~~ args where
+	args = [
+		"time" ~% formatTime defaultTimeLocale tmFmt tm,
+		"level" ~% l,
+		"component" ~% comp,
+		"scope" ~% scope,
+		"message" ~% msg]
+
+-- | Text log converter with default time format
+text ∷ FormatResult r ⇒ Converter r
+text = textFmt defaultTimeFormat "{time:cyan}\t{level}\t{component:magenta}:{scope:green}> {message}"
+
+shortText ∷ FormatResult r ⇒ Converter r
+shortText = textFmt defaultTimeFormat "{level}\t{component:magenta}: {message}"
+
+msgOnly ∷ FormatResult r ⇒ Converter r
+msgOnly = textFmt defaultTimeFormat "{message}"
