packages feed

json-tracer 0.0.1.1 → 0.0.1.2

raw patch · 6 files changed

+126/−31 lines, 6 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- JSON.Trace: dictTraceT :: (MonadIO m) => TracerT (Dict c) m a -> m (a, Dict c)

Files

README.md view
@@ -1,2 +1,120 @@ # json-tracer Type-safe polymorphic json-structured tracing library++This library provides two modules+- `Data.PolyDict`: type-safe, polymorphic, and json-structured dictionary+- `Control.Monad.CTrace`: a monad that enables contextual tracing++# PolyDict+PolyDict is a hash dict like JSON, but it is typed.+`Dict n` is a dictinary whose fields are typed accoding to `Assoc n`. +That is, each field has type `Key k` (which is a proxy of type-level symbol `k`) and +`Assoc n k` is the type of values associated with the key. ++Basically, users define a `data` that represents the namespace of the `Dict`.+For example:+```haskell+data Main+```++Then, one can define the type of `Dict n` by adding rules for type family `Assoc n k` like this:+```haskell+type instance Assoc Main "elapsed_time" = NominalDiffTime+type instance Assoc Main "tag" = String+```++The RHS type of the `Assoc n k` must satisfy the `DictValue v` constraint.+```hakell+type family DictValue v :: Constraint where+    DictValue v = (Eq v, Show v, ToJSON v)+```+As far as the author knows, any `ToJSON v` value satisfy this constraint.++Note: `Dict n` is allowed as the RHS type as `Dict n` satisfies the `DictValue` constraint. Hence recursive structures can be handled.++Since the definition of type family is open, users don't have to define all rules at the same module.+It's totally free to add other fields on demand, as long as there are no conflicting keys.+When such confliction occurs, the compiler reports it as an error.+```haskell+type instance Assoc Main "tag" = Int +-- this would be compile error because the key "tag" is conflicting to the previous definition.+```++Values in `Dict` are obtained and updated by `lookup` and `insert` function.+```haskell+lookup :: (KnownSymbol k, DictValue v, Assoc n k ~ v) => Key k -> Dict n -> Maybe v+insert :: (KnownSymbol k, DictValue v, Assoc n k ~ v) => Key k -> v -> Dict n -> Dict n+```+With the `OverloadedLabels` extention, user can write `#foo` as the key for the field `"foo"`.++## Examples+```haskell+ghci> let v = insert #tag "sample" empty +ghci> v+{"tag": "sample"}+ghci> lookup #tag v+Just "sample"+ghci> lookup #elapsed_time v+Nothing+```++Instead, lenses can be used to access thouse fields with `access` function.+```haskell+access  :: forall n k v. (KnownSymbol k, DictValue v, Assoc n k ~ v) => Key k -> Lens' (Dict n) (Maybe v)+access' :: forall n k v. (KnownSymbol k, DictValue v, Assoc n k ~ v) => Key k -> v -> Lens' (Dict n) v+```++## Examples+```haskell+ghci> let v = empty & access #tag ?~ "sample"+ghci> v+{"tag": "sample"}+ghci> v ^. access #tag+Just "sample"+```++# Tracer Monad+`TracerT c m a` is the type of a monad transformer that enables contextual tracing.+`update` and `zoom` operations can be performed in this monad transformer.++`update` is the action to modifies the value of context.+```haskell+update :: Monad m => (c -> c) -> TracerT c m ()+```+For example, you can count the number of calls of function `f` +by inserting `update succ :: TracerT Int m ()` for each call of `f`.++Note: although you can modify the value, you cannot get the current value in this monad. +This is intentional, to make it easy to disable tracing.++`zoom` is the action to change the context of tracing.+```haskell+zoom :: ASetter' c c' -> TracerT c' m a -> TracerT c m a+```++# Complete Example+```haskell+{-# LANGUAGE TypeFamilies, DataKinds, OverloadedLabels #-}+import Data.PolyDict+import Control.Monad.CTrace+import Lens.Micro+import Control.Monad++data Main+data Sub++type instance Assoc Main "sub" = Dict Sub+type instance Assoc Sub  "count" = Int++subFunc :: Monad m => Int -> TracerT (Dict Sub) m ()+subFunc n = replicateM_ n (update (access' #count 0 %~ succ))++mainFunc :: Monad m => TracerT (Dict Main) m ()+mainFunc = zoom (access' #sub empty) (subFunc 42)++main :: IO ()+main = do+    (_,d) <- ioTracerT empty mainFunc+    print d+-- > {"sub": {"count": 42}}+```
example/Fib.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE DataKinds, TypeFamilies, OverloadedLabels #-} module Fib where import Lens.Micro-import JSON.Trace+import Control.Monad.CTrace+import Data.PolyDict  data Fib type instance Assoc Fib "arg"  = Int
example/Fib2.hs view
@@ -2,7 +2,8 @@ module Fib2 where import Fib(Fib) import Lens.Micro-import JSON.Trace+import Control.Monad.CTrace+import Data.PolyDict import Control.Monad.State.Strict import qualified Data.IntMap as M 
example/Main.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DataKinds, TypeFamilies, OverloadedLabels #-}-import JSON.Trace+import Control.Monad.CTrace+import Data.PolyDict import Data.Aeson.Encode.Pretty import qualified Data.ByteString.Lazy as B import Data.Time(NominalDiffTime, getCurrentTime, diffUTCTime)@@ -36,7 +37,7 @@ main :: IO () main = do     forM_ [doit1,doit2] $ \doit -> do-        (r, d) <- dictTraceT doit+        (r, d) <- ioTracerT empty doit         B.putStr (encodePretty d)         putStrLn ""         print r
json-tracer.cabal view
@@ -1,5 +1,5 @@ name:                json-tracer-version:             0.0.1.1+version:             0.0.1.2 synopsis:            A polymorphic, type-safe, json-structured tracing library description:              .@@ -22,7 +22,6 @@   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,
− src/JSON/Trace.hs
@@ -1,25 +0,0 @@--{-|-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-