diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2017
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# json-tracer
+Type-safe polymorphic json-structured tracing library
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/example/Fib.hs b/example/Fib.hs
new file mode 100644
--- /dev/null
+++ b/example/Fib.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE DataKinds, TypeFamilies, OverloadedLabels #-}
+module Fib where
+import Lens.Micro
+import JSON.Trace
+
+data Fib
+type instance Assoc Fib "arg"  = Int
+type instance Assoc Fib "ret"  = Int
+type instance Assoc Fib "left"  = Dict Fib
+type instance Assoc Fib "right" = Dict Fib
+
+fib :: Monad m => Int -> TracerT (Dict Fib) m Int
+fib n = do
+    update (access #arg ?~ n)
+    r <- case n of
+        0 -> return 0
+        1 -> return 1
+        n -> (+) <$> zoom (access' #left  empty) (fib (n-1)) 
+                 <*> zoom (access' #right empty) (fib (n-2))
+    update (access #ret ?~ r)
+    return r
+
+
+    
diff --git a/example/Fib2.hs b/example/Fib2.hs
new file mode 100644
--- /dev/null
+++ b/example/Fib2.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE DataKinds, TypeFamilies, OverloadedLabels, FlexibleContexts #-}
+module Fib2 where
+import Fib(Fib)
+import Lens.Micro
+import JSON.Trace
+import Control.Monad.State.Strict
+import qualified Data.IntMap as M
+
+type instance Assoc Fib "calls"  = [(Int,Int)]
+
+memoFib :: (MonadState (M.IntMap Int) m, 
+            MonadTrace (Dict Fib) m) => Int -> m Int
+memoFib n = do
+    memo <- get
+    case M.lookup n memo of
+        Just v -> return v
+        Nothing -> do
+            v <- case n of
+                0 -> return 0
+                1 -> return 1
+                _ -> (+) <$> memoFib (n-1) <*> memoFib (n-2)
+            modify' (M.insert n v)
+            update $ access' #calls [] %~ ((n,v):)
+            return v
+
+fib :: Monad m => Int -> TracerT (Dict Fib) m Int
+fib n = do
+    update (access #arg ?~ n)
+    r <- evalStateT (memoFib n) (M.empty)
+    update (access #ret ?~ r)
+    return r
diff --git a/example/Main.hs b/example/Main.hs
new file mode 100644
--- /dev/null
+++ b/example/Main.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE DataKinds, TypeFamilies, OverloadedLabels #-}
+import JSON.Trace
+import Data.Aeson.Encode.Pretty
+import qualified Data.ByteString.Lazy as B
+import Data.Time(NominalDiffTime, getCurrentTime, diffUTCTime)
+import Control.Monad.Trans
+import Control.Monad
+import Lens.Micro
+import qualified Fib
+import qualified Fib2
+
+data Main
+type instance Assoc Main "elapsed_time" = NominalDiffTime
+type instance Assoc Main "tag" = String
+type instance Assoc Main "fib" = (Dict Fib.Fib)
+
+doit1 :: TracerT (Dict Main) IO Int
+doit1 = do
+  update $ access #tag ?~ "doit1"
+  t_start <- liftIO getCurrentTime
+  r <- zoom (access' #fib empty) (Fib.fib 5)
+  t_end <- liftIO getCurrentTime
+  update $ access #elapsed_time ?~ (diffUTCTime t_end t_start)
+  return r
+
+doit2 :: TracerT (Dict Main) IO Int
+doit2 = do
+  update $ access #tag ?~ "doit2"
+  t_start <- liftIO getCurrentTime
+  r <- zoom (access' #fib empty) (Fib2.fib 5)
+  t_end <- liftIO getCurrentTime
+  update $ access #elapsed_time ?~ (diffUTCTime t_end t_start)
+  return r
+
+
+main :: IO ()
+main = do
+    forM_ [doit1,doit2] $ \doit -> do
+        (r, d) <- dictTraceT doit
+        B.putStr (encodePretty d)
+        putStrLn ""
+        print r
+    
diff --git a/json-tracer.cabal b/json-tracer.cabal
new file mode 100644
--- /dev/null
+++ b/json-tracer.cabal
@@ -0,0 +1,85 @@
+name:                json-tracer
+version:             0.0.1.0
+-- synopsis:
+description:         
+    .
+    An polymorphic, type-safe, structured tracing library.
+
+homepage:            https://github.com/autotaker/jsontracer#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Taku Terao
+maintainer:          autotaker@gmail.com
+copyright:           2017 Taku Terao
+category:            Control
+build-type:          Simple
+extra-source-files:  README.md
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  ghc-options:         -O2 -W
+  exposed-modules:     Data.PolyDict
+                     , Control.Monad.Trans.CTrace
+                     , Control.Monad.CTrace
+                     , JSON.Trace
+  build-depends:       base >= 4.7 && <5,
+                       mtl >=2.2 && <2.3, 
+                       unordered-containers >= 0.2.8,
+                       hashable >= 1.2.6 &&  < 1.2.7,
+                       ghc-prim >= 0.5 && < 0.6,
+                       microlens > 0.4.0,
+                       microlens-ghc > 0.4.0,
+                       transformers >= 0.5 && < 0.6,
+                       containers >= 0.5 && < 0.6,
+                       text >= 1.2.2,
+                       aeson >= 0.11,
+                       template-haskell >= 2.11
+  default-extensions:  FlexibleInstances
+                     , FlexibleContexts
+                     , BangPatterns
+                     , MultiParamTypeClasses
+                     , ScopedTypeVariables
+                     , GADTs
+                     , OverloadedLabels
+                     , DataKinds
+                     , TypeFamilies
+                     , RankNTypes
+                     , TemplateHaskell
+  default-language:    Haskell2010
+
+test-suite unit-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  other-modules:       PolyDictSpec
+  build-depends:       base
+                     , json-tracer
+                     , hspec >= 2.2
+                     , hspec-core >= 2.2
+                     , hspec-expectations >= 0.7
+                     , hspec-discover
+                     , microlens
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+test-suite example
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      example
+  main-is:             Main.hs
+  other-modules:       Fib, Fib2
+  build-depends:       base
+                     , json-tracer
+                     , microlens
+                     , aeson
+                     , aeson-pretty
+                     , time
+                     , containers
+                     , bytestring
+                     , mtl
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/autotaker/jsontracer
diff --git a/src/Control/Monad/CTrace.hs b/src/Control/Monad/CTrace.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/CTrace.hs
@@ -0,0 +1,93 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving, FunctionalDependencies, UndecidableInstances #-}
+-- |
+-- Module      : Control.Monad.CTrace
+-- Copyright   : (c) Taku Terao, 2017 
+-- License     : BSD3 
+-- Maintainer  : autotaker@gmail.com 
+-- Stability   : experimental 
+-- Portability : GHC
+-- Contextual tracing monad, mtl-compatible.
+
+module Control.Monad.CTrace( MonadTrace(..)
+                           , TracerT
+                           , zoom
+                           , runTracerT
+                           , noTracerT
+                           , ioTracerT) where
+
+import Control.Monad.Trans.CTrace hiding (update)
+import qualified Control.Monad.Trans.CTrace as T(update)
+import Lens.Micro
+
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.List
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Cont
+import qualified Control.Monad.Trans.State.Strict as Strict
+import qualified Control.Monad.Trans.State.Lazy as Lazy
+import qualified Control.Monad.Trans.Writer.Strict as Strict
+import qualified Control.Monad.Trans.Writer.Lazy as Lazy
+import qualified Control.Monad.Trans.RWS.Strict as Strict
+import qualified Control.Monad.Trans.RWS.Lazy as Lazy
+import Control.Monad.Trans.Class(lift)
+
+-- | contextual tracing monad
+class Monad m => MonadTrace c m | m -> c where
+    -- | Apply the specified function to the tracing context
+    update :: (c -> c) -> m ()
+    -- | monomorphic version of 'zoom' operation
+    zoom'  :: ASetter' c c -> m a -> m a
+
+instance Monad m => MonadTrace c (TracerT c m) where
+    update = T.update 
+    zoom' = zoom
+
+instance MonadTrace c m => MonadTrace c (ReaderT r m) where
+    update = lift . update
+    zoom'  = mapReaderT . zoom'
+
+instance (Monoid w, MonadTrace c m) => MonadTrace c (Strict.WriterT w m) where
+    update = lift . update
+    zoom' = Strict.mapWriterT .zoom'
+
+instance (Monoid w, MonadTrace c m) => MonadTrace c (Lazy.WriterT w m) where
+    update = lift . update
+    zoom' = Lazy.mapWriterT .zoom'
+
+instance (MonadTrace c m) => MonadTrace c (ExceptT e m) where
+    update = lift . update
+    zoom' = mapExceptT . zoom'
+
+instance (MonadTrace c m) => MonadTrace c (IdentityT m) where
+    update = lift . update
+    zoom' = mapIdentityT . zoom'
+
+instance (MonadTrace c m) => MonadTrace c (ListT m) where
+    update = lift . update
+    zoom' = mapListT . zoom'
+
+instance (MonadTrace c m) => MonadTrace c (MaybeT m) where
+    update = lift . update
+    zoom' = mapMaybeT . zoom'
+
+instance (MonadTrace c m) => MonadTrace c (Strict.StateT s m) where
+    update = lift . update
+    zoom' = Strict.mapStateT . zoom'
+
+instance (MonadTrace c m) => MonadTrace c (Lazy.StateT s m) where
+    update = lift . update
+    zoom' = Lazy.mapStateT . zoom'
+
+instance (Monoid w, MonadTrace c m) => MonadTrace c (Strict.RWST r w s m) where
+    update = lift . update
+    zoom' = Strict.mapRWST . zoom'
+
+instance (Monoid w, MonadTrace c m) => MonadTrace c (Lazy.RWST r w s m) where
+    update = lift . update
+    zoom' = Lazy.mapRWST . zoom'
+
+instance (MonadTrace c m) => MonadTrace c (ContT r m) where
+    update = lift . update
+    zoom' = mapContT . zoom'
diff --git a/src/Control/Monad/Trans/CTrace.hs b/src/Control/Monad/Trans/CTrace.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/Trans/CTrace.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving, FunctionalDependencies, UndecidableInstances, StandaloneDeriving #-}
+-- |
+-- Module      : Control.Monad.CTrace
+-- Copyright   : (c) Taku Terao, 2017 
+-- License     : BSD3 
+-- Maintainer  : autotaker@gmail.com 
+-- Stability   : experimental 
+-- Portability : GHC
+-- Contextual tracing monad transformer. transformers-compatible.
+module Control.Monad.Trans.CTrace(TracerT, runTracerT, zoom, update, noTracerT, ioTracerT) where
+
+import Control.Monad.Cont.Class
+import Control.Monad.Reader
+import Control.Monad.Writer.Class
+import Control.Monad.Error.Class
+import Control.Monad.State.Class
+import Control.Monad.RWS.Class
+import Lens.Micro
+import Data.IORef
+
+-- | Contextual tracing monad transformer type.
+--   Tracing context c can be modified through this monad.
+newtype TracerT c m a = TracerT (ReaderT (Action c m) m a)
+   deriving(Functor,Monad,Applicative, MonadIO, MonadFix)
+
+type Action c m = (c -> c) -> m ()
+
+-- | Perform modification on the tracing context
+update :: Monad m => (c -> c) -> TracerT c m ()
+update f = TracerT $ ReaderT $ \tracer -> tracer f
+{-# INLINE update #-}
+
+-- | Change the tracing context. 
+zoom :: ASetter' c c' -> TracerT c' m a -> TracerT c m a
+zoom l (TracerT m) = TracerT $ ReaderT $ \action ->
+    runReaderT m (\updateFunc -> action (over l updateFunc))
+{-# INLINE zoom #-}
+
+instance MonadTrans (TracerT c) where
+    lift = TracerT . lift
+    {-# INLINE lift #-}
+
+-- | Run the tracer monad with the specified update action.
+runTracerT :: ((c -> c) -> m ()) -> TracerT c m a -> m a
+runTracerT action (TracerT m) = runReaderT m action
+{-# INLINE runTracerT #-}
+
+-- | Run the tracer monad without tracing.
+noTracerT :: Monad m => TracerT c m a -> m a
+noTracerT = runTracerT (const (return ()))
+{-# INLINE noTracerT #-}
+
+-- | Run the tracer monad with update action implemented by 'IORef'
+ioTracerT :: MonadIO m => c -> TracerT c m a -> m (a,c)
+ioTracerT init m = do
+    r <- liftIO $ newIORef init
+    v <- runTracerT (liftIO . modifyIORef' r) m
+    c <- liftIO $ readIORef r
+    return (v,c)
+{-# INLINE ioTracerT #-}
+
+instance MonadReader r m => MonadReader r (TracerT c m) where
+    ask = lift ask
+    reader = lift . reader
+    local f (TracerT m) = TracerT (ReaderT $ local f . runReaderT m)
+
+deriving instance MonadWriter w m => MonadWriter w (TracerT c m) 
+deriving instance MonadError e m => MonadError e (TracerT c m) 
+deriving instance MonadState s m => MonadState s (TracerT c m) 
+deriving instance MonadRWS r w s m => MonadRWS r w s (TracerT c m)
+deriving instance MonadCont m => MonadCont (TracerT c m)
+
+    
diff --git a/src/Data/PolyDict.hs b/src/Data/PolyDict.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/PolyDict.hs
@@ -0,0 +1,129 @@
+{-# LANGUAGE MagicHash, MultiParamTypeClasses, TypeOperators, GeneralizedNewtypeDeriving #-}
+
+-- |
+-- Module      : Data.PolyDict 
+-- Copyright   : (c) Taku Terao, 2017 
+-- License     : BSD3 
+-- Maintainer  : autotaker@gmail.com 
+-- Stability  : experimental 
+-- Portability : GHC
+-- Type-safe, polymorphic dictionary. 
+
+module Data.PolyDict( DictValue, Assoc, Dict, Key, lookup, insert, access, access', empty) where
+
+import Prelude hiding(lookup)
+
+import Data.Aeson
+import Data.Hashable
+import qualified Data.HashMap.Strict as H
+import Data.Kind(Constraint)
+import Data.List(intersperse)
+import Data.Proxy
+import Data.Text (pack)
+
+import Data.Type.Equality
+
+import GHC.TypeLits
+import GHC.Prim(Proxy#, proxy#)
+import GHC.OverloadedLabels
+
+import Lens.Micro
+import Unsafe.Coerce
+
+-- | 'DictValue' is the constraint for values can be inserted into 'Dict'
+type family DictValue v :: Constraint where
+    DictValue v = (Eq v, Show v, ToJSON v)
+
+-- | 'Assoc' n k defines the type of value associated with key k.
+--   Parameter n defines the namespace for dictionary fields. For example:
+--   
+-- > data Log
+-- > type instance Assoc Log "argments" = [String]
+-- > type instance Assoc Log "count" = Int
+-- Then 'Dict' Log is a dictionary type with (at least) two fields "arguments" and "count".
+--
+-- One can access the fields by using 'insert' and 'lookup'.
+--
+-- >>> insert #count 0 (empty :: Dict Log)
+-- {"count": 0}
+-- >>> lookup #count (insert #count 0 (empty :: Dict Log))
+-- Just 0
+--
+-- Or by using lenses:
+--
+-- >>> import Lens.Micro
+-- >>> (empty :: Dict Log) & (access #count ?~ 1) . (access #arguments ?~ ["a","b","c"])
+-- {"arguments": ["a","b","c"], "count": 1}
+--
+type family Assoc n (k :: Symbol)
+
+-- | A polymorphic, type-safe dictinary type where the parameter 'n' represents the namespace of dictionary fields.
+newtype Dict n = Dict (H.HashMap (Hashed String) (Entry n))
+  deriving(Eq)
+
+instance ToJSON (Dict n) where
+    toJSON (Dict dict) = 
+        object [ pack (symbolVal' k) .= toJSON v | (Entry k v) <- H.elems dict ]
+
+instance Eq (Entry n) where
+    Entry k1 v1 == Entry k2 v2 =
+        case f k1 k2 of
+            Just Refl -> v1 == v2
+            Nothing -> False
+        where
+        f :: (KnownSymbol k1, KnownSymbol k2) => Proxy# k1 -> Proxy# k2 -> Maybe (k1 :~: k2)
+        f _ _ = sameSymbol Proxy Proxy
+    {-# INLINE (==) #-}
+
+
+instance Show (Dict n) where
+    showsPrec _ (Dict d) = 
+        showChar '{' . 
+           foldl1 (.) (intersperse (showString ", ") 
+               [ shows (symbolVal' k) . showString ": " . shows v | (Entry k v) <- H.elems d ])
+        . showChar '}'
+
+data Entry n where
+    Entry :: (KnownSymbol k, DictValue v, Assoc n k ~ v) => Proxy# k -> v -> Entry n
+
+-- | The type of keys. With the OverloadedLabels extenstion, #foo is the key for field "foo"
+--   
+--
+newtype Key (k :: Symbol) = Key (Proxy k)
+
+instance k ~ k' => IsLabel k (Key k') where
+    fromLabel _ = Key Proxy
+    {-# INLINE fromLabel #-}
+
+-- | Return the value associated with the key.
+lookup :: (KnownSymbol k, DictValue v, Assoc n k ~ v) => Key k -> Dict n -> Maybe v
+lookup key dict = dict ^. access key
+{-# INLINE lookup #-}
+
+-- | Insert the value at the specified key of the dictionary
+insert :: (KnownSymbol k, DictValue v, Assoc n k ~ v) => Key k -> v -> Dict n -> Dict n
+insert key value = access key ?~ value
+{-# INLINE insert #-}
+
+-- | Return the empty dictionary.
+empty :: Dict n
+empty = Dict H.empty
+{-# INLINE empty #-}
+
+-- | Give the lens accessing to the value associated with the key.
+access :: forall n k v. (KnownSymbol k, DictValue v, Assoc n k ~ v) => Key k -> Lens' (Dict n) (Maybe v)
+access key = lens getter setter
+    where
+    k = hashed (symbolVal key)
+    getter (Dict dict) = case H.lookup k dict of
+        Just (Entry _ v) -> Just (unsafeCoerce v)
+        Nothing -> Nothing
+    setter (Dict dict) Nothing = Dict $ H.delete k dict
+    setter (Dict dict) (Just v) = Dict $ H.insert k (Entry (proxy# :: Proxy# k) v) dict
+{-# INLINE access #-}
+
+-- | Same as 'access' but requires the default value.
+access' :: forall n k v. (KnownSymbol k, DictValue v, Assoc n k ~ v) => Key k -> v -> Lens' (Dict n) v
+access' key def = access key . non def
+{-# INLINE access' #-}
+
diff --git a/src/JSON/Trace.hs b/src/JSON/Trace.hs
new file mode 100644
--- /dev/null
+++ b/src/JSON/Trace.hs
@@ -0,0 +1,25 @@
+
+{-|
+Module      : JSON.Trace
+Copyright   : (c) Taku Terao, 2017 
+License     : BSD3 
+Maintainer  : autotaker@gmail.com 
+Stability  : experimental 
+Portability : GHC
+type-safe json-structured tracing
+
+-}
+
+module JSON.Trace( dictTraceT 
+                 , module Data.PolyDict 
+                 , module Control.Monad.CTrace 
+                 )where
+   
+import Data.PolyDict    
+import Control.Monad.Trans
+import Control.Monad.CTrace
+
+-- | run the tracer monad whose tracing context is 'Dict'
+dictTraceT :: (MonadIO m) => TracerT (Dict c) m a -> m (a, Dict c)
+dictTraceT = ioTracerT empty
+
diff --git a/test/PolyDictSpec.hs b/test/PolyDictSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/PolyDictSpec.hs
@@ -0,0 +1,42 @@
+{-# LANGUAGE OverloadedLabels, DataKinds,TypeFamilies #-}
+module PolyDictSpec(spec) where
+
+import Data.PolyDict(Assoc,Dict)
+import qualified Data.PolyDict as D
+
+import Test.Hspec.Core.Spec
+import Test.Hspec.Expectations
+import Lens.Micro
+
+data Test
+type instance Assoc Test "foo" = String
+type instance Assoc Test "bar" = Bool
+type instance Assoc Test "baz" = Dict Test
+
+dict0 :: Dict Test
+dict0 = D.empty
+
+dict1 = dict0 & (D.access #foo ?~ "Foo")
+              . (D.access #bar ?~ True )
+              . (D.access #baz ?~ dict0)
+
+specDict0 :: Spec
+specDict0 = do
+  describe "empty" $ do
+    it "lookup always be Nothing" $ do
+        D.lookup #foo dict0 `shouldBe` Nothing
+        D.lookup #bar dict0 `shouldBe` Nothing
+        D.lookup #baz dict0 `shouldBe` Nothing
+
+specDict1 :: Spec
+specDict1 = do
+  describe "insert" $ do
+    it "has" $ do
+      D.lookup #foo dict1 `shouldBe` (Just "Foo")
+      D.lookup #bar dict1 `shouldBe` (Just True)
+      D.lookup #baz dict1 `shouldBe` (Just dict0)
+
+spec :: Spec
+spec = do
+    specDict0
+    specDict1
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
