co-log-effectful (empty) → 0.0.0.1
raw patch · 6 files changed
+295/−0 lines, 6 filesdep +QuickCheckdep +basedep +bytestring
Dependencies added: QuickCheck, base, bytestring, co-log-core, co-log-effectful, effectful, effectful-core, effectful-plugin, tasty, tasty-golden, tasty-hunit, tasty-quickcheck, text
Files
- CHANGELOG.md +5/−0
- LICENSE +30/−0
- co-log-effectful.cabal +109/−0
- src/Effectful/Colog.hs +96/−0
- test/Effectful/CologTest.hs +54/−0
- test/Main.hs +1/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for placeholder++## 0.0.0.1 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2023, Eldritch Cookie++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 Eldritch Cookie 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.
+ co-log-effectful.cabal view
@@ -0,0 +1,109 @@+cabal-version: 3.4++-- The cabal-version field refers to the version of the .cabal specification,+-- and can be different from the cabal-install (the tool) version and the+-- Cabal (the library) version you are using. As such, the Cabal (the library)+-- version used must be equal or greater than the version stated in this field.+-- Starting from the specification version 2.2, the cabal-version field must be+-- the first thing in the cabal file.++-- Initial package description 'placeholder' generated by+-- 'cabal init'. For further documentation, see:+-- http://haskell.org/cabal/users-guide/+--+-- The name of the package.+name: co-log-effectful+synopsis: effectful log effect using co-log-core+description:+ co-log-effectful provides a `Log` effect for effectful that can use `LogAction`s in the `Eff` monad++category: library, logging, control, bsd3 ++-- The package version.+-- See the Haskell package versioning policy (PVP) for standards+-- guiding when and how versions should be incremented.+-- https://pvp.haskell.org+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 0.0.0.1+homepage: https://github.com/eldritch-cookie/co-log-effectful+bug-reports: https://github.com/eldritch-cookie/co-log-effectful/issues++-- The license under which the package is released.+license: BSD-3-Clause++-- The file containing the license text.+license-file: LICENSE++-- The package author(s).+author: Eldritch Cookie++-- An email address to which users can send suggestions, bug reports, and patches.+maintainer: eldritch.cookie@disroot.org++-- A copyright notice.+-- copyright:+build-type: Simple++-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.+extra-doc-files: CHANGELOG.md+tested-with: GHC ==9.6.6 || ==9.10.1++-- Extra source files to be distributed with the package, such as examples, or a tutorial module.+-- extra-source-files:++common deps+ ghc-options: -Wall -fplugin=Effectful.Plugin+ build-depends:+ , base >=4.18.2 && <5+ , bytestring >=0.11.5 && <1+ , co-log-core >=0.3.2 && <1+ , effectful >=2.3.1 && <3+ , effectful-core >=2.3.1 && <3+ , effectful-plugin >=1.1.0 && <2+ , text >=2.0.2 && <3++ default-extensions:+ DataKinds+ DerivingStrategies+ DerivingVia+ DuplicateRecordFields+ FunctionalDependencies+ NoCUSKs+ NoFieldSelectors+ NoStarIsType+ OverloadedLists+ OverloadedRecordDot+ OverloadedStrings+ QuantifiedConstraints+ ScopedTypeVariables+ TypeFamilyDependencies+ TypeOperators++ default-language: GHC2021++library+ import: deps+ exposed-modules: Effectful.Colog+ hs-source-dirs: src++test-suite co-log-effectful-test+ import: deps+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Main.hs+ other-modules: Effectful.CologTest+ build-depends:+ , co-log-effectful+ , QuickCheck >=2.14.3+ , tasty >=1.4.3+ , tasty-golden >=2.3.5+ , tasty-hunit >=0.10.2+ , tasty-quickcheck >=0.10.2++ build-tool-depends: tasty-discover:tasty-discover++source-repository head+ type: git+ location: https://github.com/eldritch-cookie/co-log-effectful
+ src/Effectful/Colog.hs view
@@ -0,0 +1,96 @@+module Effectful.Colog (+ -- * Effect+ Log,+ LogEff,+ logMsg,+ injectLog,++ -- ** Handlers+ runLogAction,+ runLogWriter,++ -- ** 'LogAction's+ tellLogEff,++ -- *** 'FileSystem' constrained+ byteStringLogEff,+ textLogEff,++ -- * Re-exports+ module Colog.Core.Action,+)+where++import Colog.Core.Action+import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.Kind+import Data.Text (Text)+import Data.Text.Encoding (encodeUtf8)+import Effectful+import Effectful.Dispatch.Static+import Effectful.FileSystem (FileSystem)+import Effectful.FileSystem.IO.ByteString (hPutStr)+import Effectful.Internal.Env (Env, Relinker (..), consEnv, unconsEnv)+import Effectful.Internal.Utils (inlineBracket)+import Effectful.Writer.Static.Shared (Writer, runWriter, tell)+import System.IO (Handle)++-- | Provides the ability to log with an implicit 'LogEff'+type Log :: Type -> Effect+data Log msg m a++type instance DispatchOf (Log msg) = Static NoSideEffects+data instance StaticRep (Log msg) where+ MkLog :: forall localEs msg. !(Env localEs) -> !(LogEff localEs msg) -> StaticRep (Log msg)++-- | 'LogAction' limited to the 'Eff' monad+type LogEff es msg = LogAction (Eff es) msg++unLogEff :: forall es msg. LogEff es msg -> msg -> Env es -> IO ()+unLogEff le = unEff . unLogAction le++relinkLog :: forall msg. Relinker StaticRep (Log msg)+relinkLog = Relinker $ \relink (MkLog localEs act) -> do+ newLocalEs <- relink localEs+ pure $ MkLog newLocalEs act++-- | runs the 'Log' effect using the provided action this is the most general runner+runLogAction :: forall es msg a. LogEff es msg -> Eff (Log msg : es) a -> Eff es a+runLogAction logAct act = unsafeEff $ \env -> do+ inlineBracket+ (consEnv (MkLog env logAct) relinkLog env)+ unconsEnv+ (\es -> unEff act es)++-- | runs the 'Log' effect using 'tellLogEff' and then handles the 'Writer' effect+runLogWriter :: forall es msg a. (Monoid msg) => Eff (Log msg : es) a -> Eff es (a, msg)+runLogWriter = runWriter . runLogAction tellLogEff . inject++-- | logs a message using the implicit 'LogEff'+logMsg :: forall msg es. (Log msg :> es) => msg -> Eff es ()+logMsg message = do+ MkLog env act <- getStaticRep+ unsafeEff_ $ unLogEff act message env++-- untested++-- | converts a 'LogEff' into another compatible 'LogEff'+injectLog :: forall (xs :: [Effect]) (es :: [Effect]) a. (Subset xs es) => LogEff xs a -> LogEff es a+injectLog = hoistLogAction inject++-- | 'LogEff' that delegates to a static shared 'Writer' effect+tellLogEff :: forall es msg. (Writer msg :> es, Monoid msg) => LogEff es msg+tellLogEff = LogAction tell++-- untested++-- | 'LogEff' that writes 'Text' to a 'Handle'+textLogEff :: forall es. (FileSystem :> es) => Handle -> LogEff es Text+textLogEff hdl = LogAction $ hPutStr hdl . encodeUtf8++-- untested++-- | 'LogEff' that writes 'ByteString' to a 'Handle'+byteStringLogEff :: forall es. (FileSystem :> es) => Handle -> LogEff es ByteString+byteStringLogEff hdl = LogAction $ hPutStr hdl
+ test/Effectful/CologTest.hs view
@@ -0,0 +1,54 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Effectful.CologTest where++import Data.Text (Text, pack)++-- import Test.Tasty+import Test.Tasty.QuickCheck++-- import Test.Tasty.HUnit++import Effectful+import Effectful.Colog+import Effectful.Concurrent.Async (runConcurrent, wait, withAsync)+import Effectful.Labeled+import Effectful.Provider+import Effectful.Writer.Static.Shared (runWriter)++instance Arbitrary Text where+ arbitrary = fmap pack arbitrary++prop_tellEquals :: Text -> Property+prop_tellEquals t = runPureEff $ do+ (_, t2) <- runLogWriter $ logMsg t+ pure $ t === t2++prop_labeledLogShared :: Text -> Property+prop_labeledLogShared msg =+ property @Property+ . runPureEff+ . fmap ((msg ===) . snd)+ . runLabeled runLogWriter+ . labeled+ $ logMsg msg++prop_providerLogShared :: Text -> Property+prop_providerLogShared msg =+ property @Property+ . runPureEff+ . fmap ((=== msg) . snd)+ . runWriter @Text+ . runProvider_ (runLogAction)+ $ provideWith_ (tellLogEff)+ $ logMsg @Text msg++prop_tellConcurrent :: Text -> Text -> Property+prop_tellConcurrent m1 m2 =+ ioProperty @Property+ . runEff+ . runConcurrent+ . fmap ((=== (m1 <> m2)) . snd)+ . runWriter @Text+ . runLogAction tellLogEff+ $ logMsg m1 >> withAsync (logMsg m2) (\a -> wait a >> pure ())
+ test/Main.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF tasty-discover #-}