packages feed

monad-io-adapter (empty) → 0.1.0.0

raw patch · 10 files changed

+427/−0 lines, 10 filesdep +basedep +exceptionsdep +hspecsetup-changed

Dependencies added: base, exceptions, hspec, monad-control, monad-io-adapter, monad-logger, mtl, transformers, transformers-base

Files

+ CHANGELOG.md view
@@ -0,0 +1,3 @@+# 0.1.0.0 (November 21st, 2017)++- Initial release.
+ LICENSE view
@@ -0,0 +1,13 @@+Copyright 2017 CJ Affiliate by Conversant++Permission to use, copy, modify, and/or distribute this software for any purpose+with or without fee is hereby granted, provided that the above copyright notice+and this permission notice appear in all copies.++THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF+THIS SOFTWARE.
+ README.md view
@@ -0,0 +1,15 @@+# monad-io-adapter [![Build Status](https://travis-ci.org/cjdev/monad-io-adapter.svg?branch=master)](https://travis-ci.org/cjdev/monad-io-adapter)++This Haskell package provides utilities for converting between computations parameterized via two different typeclasses, both of which can be used to abstract over monad transformer stacks with `IO` at the base. Unfortunately, both classes are frequently used in the Haskell ecosystem, since they have minor differences:++  - `MonadIO` comes from the `base` package (as of `base` version 4.9.0.0), and it provides a `liftIO` operation. It is an extremely simple typeclass, focusing exclusively on lifting `IO` actions through transformer stacks with `IO` at the base.++  - `MonadBase` comes from the `transformers-base` package, and it is a generalized version of `MonadIO`. It provides a more general `liftBase` function, which allows lifting to an arbitrary base monad.++    Generally, this additional power isn’t especially useful, but `MonadBase` appears most often through `MonadBaseControl`, a subclass from the `monad-control` package that enables lifting operations that accept an action in negative position. This class has no `IO`-specialized equivalent (not directly, at least), so it often appears in lifted “control” operations.++Due to these typeclasses being unrelated, it’s not entirely uncommon to end up with type signatures like `(MonadIO m, MonadBaseControl IO m) => ...`, which are a little silly, since `MonadBaseControl IO` really includes all the power of `MonadIO`.++For more information, [see the documentation on Hackage][monad-io-adapter].++[monad-io-adapter]: https://hackage.haskell.org/package/monad-io-adapter
+ Setup.hs view
@@ -0,0 +1,7 @@+-- This script is used to build and install your package. Typically you don't+-- need to change it. The Cabal documentation has more information about this+-- file: <https://www.haskell.org/cabal/users-guide/installing-packages.html>.+import qualified Distribution.Simple++main :: IO ()+main = Distribution.Simple.defaultMain
+ monad-io-adapter.cabal view
@@ -0,0 +1,75 @@+-- This file has been generated from package.yaml by hpack version 0.18.1.+--+-- see: https://github.com/sol/hpack++name:           monad-io-adapter+version:        0.1.0.0+synopsis:       Adapters between MonadIO and MonadBase IO.+description:    This package provides utilities for converting between computations+                parameterized via two different typeclasses 'MonadIO' and 'MonadBase', both of+                which can be used to abstract over monad transformer stacks with 'IO' at the+                base. Unfortunately, both classes are frequently used in the Haskell+                ecosystem, since they have minor differences.+                .+                Due to these typeclasses being unrelated, it’s not entirely uncommon to end up+                with type signatures like @('MonadIO' m, 'MonadBaseControl' 'IO' m) => ...@,+                which are a little silly, since @'MonadBaseControl' 'IO'@ really includes all+                the power of 'MonadIO'.+                .+                To help alleviate this problem, this package provides a set of utilities for+                converting between the two constraints in situations where possible.+category:       Control+homepage:       https://github.com/cjdev/monad-io-adapter#readme+bug-reports:    https://github.com/cjdev/monad-io-adapter/issues+author:         Alexis King <lexi.lambda@gmail.com>+maintainer:     Alexis King <lexi.lambda@gmail.com>+copyright:      2017 CJ Affiliate by Conversant+license:        ISC+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10++extra-source-files:+    CHANGELOG.md+    package.yaml+    README.md+    stack.yaml++source-repository head+  type: git+  location: https://github.com/cjdev/monad-io-adapter++library+  hs-source-dirs:+      src+  default-extensions: FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving KindSignatures LambdaCase MultiParamTypeClasses RankNTypes ScopedTypeVariables StandaloneDeriving TupleSections TypeApplications TypeOperators+  ghc-options: -Wall+  build-depends:+      base >= 4.9 && < 5+    , exceptions >= 0.6 && < 1+    , monad-control >= 1 && < 2+    , monad-logger+    , mtl+    , transformers+    , transformers-base+  exposed-modules:+      Control.Monad.IO.Adapter+  other-modules:+      Paths_monad_io_adapter+  default-language: Haskell2010++test-suite monad-io-adapter-test-suite+  type: exitcode-stdio-1.0+  main-is: Main.hs+  hs-source-dirs:+      test+  default-extensions: FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving KindSignatures LambdaCase MultiParamTypeClasses RankNTypes ScopedTypeVariables StandaloneDeriving TupleSections TypeApplications TypeOperators+  ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N+  build-depends:+      base+    , hspec+    , monad-io-adapter+    , transformers-base+  other-modules:+      Control.Monad.IO.AdapterSpec+  default-language: Haskell2010
+ package.yaml view
@@ -0,0 +1,72 @@+name: monad-io-adapter+version: 0.1.0.0+category: Control+synopsis: Adapters between MonadIO and MonadBase IO.+description: |+  This package provides utilities for converting between computations+  parameterized via two different typeclasses 'MonadIO' and 'MonadBase', both of+  which can be used to abstract over monad transformer stacks with 'IO' at the+  base. Unfortunately, both classes are frequently used in the Haskell+  ecosystem, since they have minor differences.++  Due to these typeclasses being unrelated, it’s not entirely uncommon to end up+  with type signatures like @('MonadIO' m, 'MonadBaseControl' 'IO' m) => ...@,+  which are a little silly, since @'MonadBaseControl' 'IO'@ really includes all+  the power of 'MonadIO'.++  To help alleviate this problem, this package provides a set of utilities for+  converting between the two constraints in situations where possible.++copyright: 2017 CJ Affiliate by Conversant+license: ISC+author: Alexis King <lexi.lambda@gmail.com>+maintainer: Alexis King <lexi.lambda@gmail.com>+github: cjdev/monad-io-adapter++extra-source-files:+- CHANGELOG.md+- package.yaml+- README.md+- stack.yaml++ghc-options: -Wall+default-extensions:+- FlexibleContexts+- FlexibleInstances+- FunctionalDependencies+- GADTs+- GeneralizedNewtypeDeriving+- KindSignatures+- LambdaCase+- MultiParamTypeClasses+- RankNTypes+- ScopedTypeVariables+- StandaloneDeriving+- TupleSections+- TypeApplications+- TypeOperators++library:+  dependencies:+  - base >= 4.9 && < 5+  - exceptions >= 0.6 && < 1+  - monad-control >= 1 && < 2+  - monad-logger+  - mtl+  - transformers+  - transformers-base+  source-dirs: src++tests:+  monad-io-adapter-test-suite:+    dependencies:+    - base+    - hspec+    - monad-io-adapter+    - transformers-base+    ghc-options:+    - -rtsopts+    - -threaded+    - -with-rtsopts=-N+    main: Main.hs+    source-dirs: test
+ src/Control/Monad/IO/Adapter.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++{-|+  This module provides utilities for converting between computations+  parameterized via two different typeclasses, both of which can be used to+  abstract over monad transformer stacks with 'IO' at the base. Unfortunately,+  both classes are frequently used in the Haskell ecosystem, since they have+  minor differences:++    * 'MonadIO' comes from the @base@ package (as of @base@ version 4.9.0.0),+      and it provides a 'liftIO' operation. It is an extremely simple typeclass,+      focusing exclusively on lifting 'IO' actions through transformer stacks+      with 'IO' at the base.++    * 'MonadBase' comes from the @transformers-base@ package, and it is a+      generalized version of 'MonadIO'. It provides a more general 'liftBase'+      function, which allows lifting to an arbitrary base monad.++        Generally, this additional power isn’t especially useful, but+        'MonadBase' appears most often through 'MonadBaseControl', a subclass+        from the @monad-control@ package that enables lifting operations that+        accept an action in negative position. This class has no+        'IO'-specialized equivalent (not directly, at least), so it often+        appears in lifted “control” operations.++  Due to these typeclasses being unrelated, it’s not entirely uncommon to end up+  with type signatures like @('MonadIO' m, 'MonadBaseControl' 'IO' m) => ...@,+  which are a little silly, since @'MonadBaseControl' 'IO'@ really includes all+  the power of 'MonadIO'.++  To help alleviate this problem, this module provides a set of utilities for+  converting between the two constraints in situations where possible. The+  'MonadIOAdapterT' transformer implements 'MonadIO' in terms of @'MonadBase'+  'IO'@, and the 'MonadBaseIOAdapterT' transformer implements @'MonadBase' 'IO'@+  in terms of 'MonadIO'.+-}+module Control.Monad.IO.Adapter+  ( -- * Adapting MonadIO in terms of MonadBase IO+    MonadIOAdapterT(MonadIOAdapterT)+  , adaptMonadIO+    -- * Adapting MonadBase IO in terms of MonadIO+  , MonadBaseIOAdapterT(MonadBaseIOAdapterT)+  , adaptMonadBaseIO+  ) where++import Control.Monad.Base (MonadBase, liftBase)+import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)+import Control.Monad.Except (MonadError)+import Control.Monad.IO.Class (MonadIO, liftIO)+import Control.Monad.Logger (MonadLogger)+import Control.Monad.Reader (MonadReader)+import Control.Monad.State (MonadState)+import Control.Monad.Trans.Class (MonadTrans)+import Control.Monad.Trans.Control+  ( ComposeSt, MonadBaseControl(..), MonadTransControl(..)+  , defaultLiftBaseWith, defaultLiftWith, defaultRestoreM, defaultRestoreT )+import Control.Monad.Trans.Identity (IdentityT(..))+import Control.Monad.Writer (MonadWriter)+++{-|+A transformer that implements 'MonadIO' in terms of @'MonadBase' 'IO'@, simply+converting any calls to 'liftIO' into calls to 'liftBase'. This makes it+possible to discharge 'MonadIO' constraints by converting them into+@'MonadBase' 'IO'@ constraints. For example, given a value with the following+type:++@+foo :: 'MonadIO' m => m ()+@++…it’s possible to convert its type signature using 'adaptMonadIO':++@+'adaptMonadIO' foo :: 'MonadBase' 'IO' m => m ()+@+-}+newtype MonadIOAdapterT m a = MonadIOAdapterT' (IdentityT m a)+  deriving ( Functor, Applicative, Monad, MonadTrans, MonadBase b+           , MonadReader r, MonadWriter w, MonadState s, MonadError e+           , MonadThrow, MonadCatch, MonadMask+           , MonadLogger )++instance MonadTransControl MonadIOAdapterT where+  type StT MonadIOAdapterT a = StT IdentityT a+  liftWith = defaultLiftWith MonadIOAdapterT' (\(MonadIOAdapterT' x) -> x)+  {-# INLINE liftWith #-}+  restoreT = defaultRestoreT MonadIOAdapterT'+  {-# INLINE restoreT #-}++instance MonadBaseControl b m => MonadBaseControl b (MonadIOAdapterT m) where+  type StM (MonadIOAdapterT m) a = ComposeSt MonadIOAdapterT m a+  liftBaseWith = defaultLiftBaseWith+  {-# INLINE liftBaseWith #-}+  restoreM = defaultRestoreM+  {-# INLINE restoreM #-}++instance MonadBase IO m => MonadIO (MonadIOAdapterT m) where+  liftIO = liftBase+  {-# INLINE liftIO #-}++pattern MonadIOAdapterT :: m a -> MonadIOAdapterT m a+pattern MonadIOAdapterT x = MonadIOAdapterT' (IdentityT x)+#if MIN_VERSION_GLASGOW_HASKELL(8,2,1,0)+{-# COMPLETE MonadIOAdapterT #-}+#endif++-- | “Runs” a 'MonadIOAdapterT' computation and returns the remaining+-- transformer stack.+adaptMonadIO :: MonadIOAdapterT m a -> m a+adaptMonadIO (MonadIOAdapterT' (IdentityT x)) = x+{-# INLINE adaptMonadIO #-}+++{-|+A transformer that implements 'MonadBase' in terms of 'MonadIO', simply+converting any calls to 'liftBase' into calls to 'liftIO'. This makes it+possible to discharge @'MonadBase' 'IO'@ constraints by converting them into+'MonadIO' constraints. For example, given a value with the following type:++@+foo :: 'MonadBase' 'IO' m => m ()+@++…it’s possible to convert its type signature using 'adaptMonadIO':++@+'adaptMonadBaseIO' foo :: 'MonadIO' m => m ()+@+-}+newtype MonadBaseIOAdapterT m a = MonadBaseIOAdapterT' (IdentityT m a)+  deriving ( Functor, Applicative, Monad, MonadTrans, MonadIO+           , MonadReader r, MonadWriter w, MonadState s, MonadError e+           , MonadThrow, MonadCatch, MonadMask+           , MonadLogger )++instance MonadIO m => MonadBase IO (MonadBaseIOAdapterT m) where+  liftBase = liftIO+  {-# INLINE liftBase #-}++pattern MonadBaseIOAdapterT :: m a -> MonadBaseIOAdapterT m a+pattern MonadBaseIOAdapterT x = MonadBaseIOAdapterT' (IdentityT x)+#if MIN_VERSION_GLASGOW_HASKELL(8,2,1,0)+{-# COMPLETE MonadIOAdapterT #-}+#endif++-- | “Runs” a 'MonadBaseIOAdapterT' computation and returns the remaining+-- transformer stack.+adaptMonadBaseIO :: MonadBaseIOAdapterT m a -> m a+adaptMonadBaseIO (MonadBaseIOAdapterT' (IdentityT x)) = x+{-# INLINE adaptMonadBaseIO #-}
+ stack.yaml view
@@ -0,0 +1,66 @@+# This file was automatically generated by 'stack init'+#+# Some commonly used options have been documented as comments in this file.+# For advanced use and comprehensive documentation of the format, please see:+# https://docs.haskellstack.org/en/stable/yaml_configuration/++# Resolver to choose a 'specific' stackage snapshot or a compiler version.+# A snapshot resolver dictates the compiler version and the set of packages+# to be used for project dependencies. For example:+#+# resolver: lts-3.5+# resolver: nightly-2015-09-21+# resolver: ghc-7.10.2+# resolver: ghcjs-0.1.0_ghc-7.10.2+# resolver:+#  name: custom-snapshot+#  location: "./custom-snapshot.yaml"+resolver: lts-9.14++# User packages to be built.+# Various formats can be used as shown in the example below.+#+# packages:+# - some-directory+# - https://example.com/foo/bar/baz-0.0.2.tar.gz+# - location:+#    git: https://github.com/commercialhaskell/stack.git+#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a+# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a+#   extra-dep: true+#  subdirs:+#  - auto-update+#  - wai+#+# A package marked 'extra-dep: true' will only be built if demanded by a+# non-dependency (i.e. a user package), and its test suites and benchmarks+# will not be run. This is useful for tweaking upstream packages.+packages:+- .+# Dependency packages to be pulled from upstream that are not in the resolver+# (e.g., acme-missiles-0.3)+# extra-deps: []++# Override default flag values for local packages and extra-deps+# flags: {}++# Extra package databases containing global packages+# extra-package-dbs: []++# Control whether we use the GHC we find on the path+# system-ghc: true+#+# Require a specific version of stack, using version ranges+# require-stack-version: -any # Default+# require-stack-version: ">=1.6"+#+# Override the architecture used by stack, especially useful on Windows+# arch: i386+# arch: x86_64+#+# Extra directories used by stack for building+# extra-include-dirs: [/path/to/dir]+# extra-lib-dirs: [/path/to/dir]+#+# Allow a newer minor version of GHC than the snapshot specifies+# compiler-check: newer-minor
+ test/Control/Monad/IO/AdapterSpec.hs view
@@ -0,0 +1,21 @@+module Control.Monad.IO.AdapterSpec (spec) where++import Control.Monad.Base (MonadBase)+import Control.Monad.IO.Class (MonadIO)+import Test.Hspec++import Control.Monad.IO.Adapter++spec :: Spec+spec = do+  describe "MonadIOAdapterT" $+    it "converts a MonadIO constraint into MonadBase IO" $+      (adaptMonadIO (pure () :: forall n. MonadIO n => n ())+          :: forall m. MonadBase IO m => m ())+        `shouldReturn` ()++  describe "MonadBaseIOAdapterT" $+    it "converts a MonadBase IO constraint into MonadIO" $+      (adaptMonadBaseIO (pure () :: forall n. MonadBase IO n => n ())+          :: forall m. MonadIO m => m ())+        `shouldReturn` ()
+ test/Main.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}