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 +3/−0
- LICENSE +13/−0
- README.md +15/−0
- Setup.hs +7/−0
- monad-io-adapter.cabal +75/−0
- package.yaml +72/−0
- src/Control/Monad/IO/Adapter.hs +154/−0
- stack.yaml +66/−0
- test/Control/Monad/IO/AdapterSpec.hs +21/−0
- test/Main.hs +1/−0
+ 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 [](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 #-}