on 70d2b29 help sign in
53 files changed+1972−2815
since splitsnapshots
unifiedsplit
.gitignore−20 .travis.yml+16−27 CHANGELOG.md−77 LICENSE+2−2 README.md+1−3 bench/Bench.hs−203 bench/TupleInstances.hs−9 ether.cabal+53−220 shell.nix−22 src/Control/Ether/TH.hs+47 src/Control/Ether/Tags.hs+155 src/Control/Ether/Util.hs+37 src/Control/Ether/Wrapped.hs+39 src/Control/Monad/Ether/Except.hs+116 src/Control/Monad/Ether/Implicit/Except.hs+40 src/Control/Monad/Ether/Implicit/Except/TH.hs+12 src/Control/Monad/Ether/Implicit/Reader.hs+40 src/Control/Monad/Ether/Implicit/State.hs+60 src/Control/Monad/Ether/Implicit/Writer.hs+64 src/Control/Monad/Ether/Reader.hs+146 src/Control/Monad/Ether/State.hs+158 src/Control/Monad/Ether/Writer.hs+156 src/Control/Monad/Trans/Ether/Except.hs+151 src/Control/Monad/Trans/Ether/Reader.hs+164 src/Control/Monad/Trans/Ether/State.hs+177 src/Control/Monad/Trans/Ether/Writer.hs+164 src/Ether.hs−25 src/Ether/Except.hs−127 src/Ether/Internal.hs−68 src/Ether/Internal/HasLens.hs−24 src/Ether/Internal/TH_TupleInstances.hs−79 src/Ether/Internal/TH_Utils.hs−14 src/Ether/Internal/Tags.hs−18 src/Ether/Internal/TupleInstances.hs−24 src/Ether/Reader.hs−236 src/Ether/State.hs−415 src/Ether/TagDispatch.hs−138 src/Ether/TaggedTrans.hs−206 src/Ether/Writer.hs−287 test/Regression.hs+174−25 test/Regression/T1.hs−50 test/Regression/T10.hs−43 test/Regression/T11.hs−50 test/Regression/T12.hs−30 test/Regression/T2.hs−28 test/Regression/T3.hs−55 test/Regression/T4.hs−24 test/Regression/T5.hs−42 test/Regression/T6.hs−64 test/Regression/T7.hs−51 test/Regression/T8.hs−51 test/Regression/T9.hs−49 test/TupleInstances.hs−9
.gitignore−20
@@ -1,21 +1 @@
1−# Cabal
21dist
3−dist-newstyle
4−.cabal-sandbox/
5−cabal.sandbox.config
6−cabal.project.local
7−.ghc.environment*
8−
9−# Profiling
10−*.prof
11−
12−# Stack
13−.stack-work
14−
15−# Emacs
16−TAGS
17−.dir-locals.el
18−
19−# Vim
20−tags
21−*.swp
.travis.yml+16−27
@@ -1,31 +1,20 @@
1−language: nix
2−
3−os:
4− - linux
5− - osx
6−
71env:
8− - HC=ghc822
9− - HC=ghc844
10− - HC=ghc861
2+ - CABALVER=1.22 GHCVER=7.10.2
3+ - CABALVER=head GHCVER=head
114
12−before_install:
13− - curl https://raw.githubusercontent.com/monadfix/nix-cabal/master/nix-cabal -o nix-cabal && chmod u+x nix-cabal
14− - travis_retry ./nix-cabal new-update
5+before-install:
6+ - travis_retry sudo add-apt-repository -y ppa:hvr/ghc
7+ - travis_retry sudo apt-get update
8+ - travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER
9+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
10+ - travis_retry cabal update
1511
16−script:
17− - ./nix-cabal new-test ether:regression
18− - ./nix-cabal new-bench ether:bench
12+install:
13+ - cabal --version
14+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
15+ - cabal install --only-dependencies --enable-tests
1916
20−cache:
21− directories:
22− - ~/.cabal
23− - ~/.ghc
24−
25−matrix:
26− # broken at the moment
27− exclude:
28− - os: osx
29− env: HC=ghc822
30− - os: osx
31− env: HC=ghc861
17+script:
18+ - cabal configure --enable-tests -v2
19+ - cabal build
20+ - cabal test
CHANGELOG.mddeleted−77
@@ -1,77 +0,0 @@
1−0.5.1.0
2−-------
3−
4−* Disable `HasLens` for tuples via cabal flag.
5−
6−0.5.0.0
7−-------
8−
9−* Support only GHC 8.0 and higher.
10−* Use the `TypeApplications` extension to get rid of `Proxy`.
11−* Remove `Control.Ether.TH`.
12−* Remove `Control.Ether.Abbr`.
13−* Unify `Dispatch` and `TaggedTrans`.
14−* Better `MonadBase` and `MonadBaseControl` instances.
15−* Add flattening for `ReaderT` and `StateT`.
16−* Add zooming for `MonadState`.
17−* Simpler module structure.
18−
19−0.4.1.0
20−-------
21−
22−* Export DispatchT newtype constructor.
23−
24−0.4.0.0
25−-------
26−
27−* Poly-kinded tags.
28−* Remove `Control.Ether.Tagged`.
29−* Replace `Control.Ether.Wrapped` with `Control.Monad.Trans.Ether.Dispatch`.
30−* Unified tagged transformer type in `Control.Monad.Trans.Ether.Tagged`.
31−* `MonadThrow`, `MonadCatch`, `MonadMask` instances.
32−* Drop `newtype-generics`.
33−* Instance search is now more strict.
34−
35−
36−0.3.1.1
37−-------
38−
39−* Fix GHC 7.8 test issue.
40−* Remove unused imports.
41−
42−
43−0.3.1.0
44−-------
45−
46−* Fix an issue with overlapping instances.
47−
48−
49−0.3.0.0
50−-------
51−
52−* `MonadBase`, `MonadTransControl`, `MonadBaseControl` instances.
53−* `MFunctor`, `MMonad` instances.
54−* Use `transformers-lift`.
55−
56−
57−0.2.1.0
58−-------
59−
60−* Constraint abbreviations: `Control.Ether.Abbr` and `Control.Ether.Implicit.Abbr`.
61−
62−
63−0.2.0.0
64−-------
65−
66−* Convenience modules `Control.Monad.Ether` and `Control.Monad.Ether.Implicit`.
67−* Remove `fmapN` and `deepN`.
68−* Remove `Control.Monad.Ether.Implicit.Except.TH`.
69−* Add `handle` and `handleT`.
70−
71−
72−0.1.0.1
73−-------
74−
75−* Fix `transformers` lower bound.
76−* Remove unused language extensions.
77−* GHC 7.8 compatibility.
LICENSE+2−2
@@ -1,4 +1,4 @@
1−Copyright (c) 2017, Vladislav Zavialov
1+Copyright (c) 2015, Index Int
22
33All rights reserved.
44
@@ -13,7 +13,7 @@ modification, are permitted provided that the following conditions are met:
1313 disclaimer in the documentation and/or other materials provided
1414 with the distribution.
1515
16− * Neither the name of Vladislav Zavialov nor the names of other
16+ * Neither the name of Index Int nor the names of other
1717 contributors may be used to endorse or promote products derived
1818 from this software without specific prior written permission.
1919
README.md+1−3
@@ -1,8 +1,6 @@
11# Ether
22
3−[![Build Status](https://img.shields.io/travis/int-index/ether.svg)](https://travis-ci.org/int-index/ether)
4−[![Hackage](https://img.shields.io/hackage/v/ether.svg)](https://hackage.haskell.org/package/ether)
5−
3+[![Build Status](https://travis-ci.org/int-index/ether.svg)](https://travis-ci.org/int-index/ether)
64
75Ether is a Haskell library that extends [mtl](https://hackage.haskell.org/package/mtl)
86and [transformers](https://hackage.haskell.org/package/transformers) with tagged
bench/Bench.hsdeleted−203
@@ -1,203 +0,0 @@
1−{-# OPTIONS -fno-warn-partial-type-signatures #-}
2−
3−module Main (main) where
4−
5−import Control.DeepSeq
6−import qualified Control.Lens as L
7−import qualified Control.Monad.Reader as M
8−import qualified Control.Monad.State as M
9−import Criterion.Main
10−import Ether
11−import TupleInstances ()
12−
13−id' :: a -> a
14−id' = id
15−{-# NOINLINE id' #-}
16−
17−readerCombinerMTL_flat_9
18− :: M.MonadReader (Int, Int, Int, Int, Int, Int, Int, Int, Int) m
19− => m ()
20−readerCombinerMTL_flat_9 = do
21− rnf <$> sequenceA
22− [ L.view L._1
23− , L.view L._2
24− , L.view L._3
25− , L.view L._4
26− , L.view L._5
27− , L.view L._6
28− , L.view L._7
29− , L.view L._8
30− , L.view L._9 ]
31−{-# NOINLINE readerCombinerMTL_flat_9 #-}
32−
33−stateCombinerMTL_flat_9
34− :: M.MonadState (Int, Int, Int, Int, Int, Int, Int, Int, Int) m
35− => m ()
36−stateCombinerMTL_flat_9 = do
37− M.modify (L.over L._1 id')
38− M.modify (L.over L._2 id')
39− M.modify (L.over L._3 id')
40− M.modify (L.over L._4 id')
41− M.modify (L.over L._5 id')
42− M.modify (L.over L._6 id')
43− M.modify (L.over L._7 id')
44− M.modify (L.over L._8 id')
45− M.modify (L.over L._9 id')
46− rnf <$> sequenceA
47− [ L.use L._1
48− , L.use L._2
49− , L.use L._3
50− , L.use L._4
51− , L.use L._5
52− , L.use L._6
53− , L.use L._7
54− , L.use L._8
55− , L.use L._9 ]
56−{-# NOINLINE stateCombinerMTL_flat_9 #-}
57−
58−run_readerCombinerMTL_flat_9 :: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> ()
59−run_readerCombinerMTL_flat_9
60− (a1, a2, a3, a4, a5, a6, a7, a8, a9) =
61− M.runReader readerCombinerMTL_flat_9 (a9, a8, a7, a6, a5, a4, a3, a2, a1)
62−
63−run_stateCombinerMTL_flat_9 ::
64− (Int, Int, Int, Int, Int, Int, Int, Int, Int) ->
65− ((), (Int, Int, Int, Int, Int, Int, Int, Int, Int))
66−run_stateCombinerMTL_flat_9
67− (a1, a2, a3, a4, a5, a6, a7, a8, a9) =
68− M.runState stateCombinerMTL_flat_9 (a9, a8, a7, a6, a5, a4, a3, a2, a1)
69−
70−readerCombinerEther_sep_9
71− :: ( MonadReader 1 Int m
72− , MonadReader 2 Int m
73− , MonadReader 3 Int m
74− , MonadReader 4 Int m
75− , MonadReader 5 Int m
76− , MonadReader 6 Int m
77− , MonadReader 7 Int m
78− , MonadReader 8 Int m
79− , MonadReader 9 Int m )
80− => m ()
81−readerCombinerEther_sep_9 = rnf <$> sequenceA
82− [ ask @1
83− , ask @2
84− , ask @3
85− , ask @4
86− , ask @5
87− , ask @6
88− , ask @7
89− , ask @8
90− , ask @9 ]
91−{-# NOINLINE readerCombinerEther_sep_9 #-}
92−
93−stateCombinerEther_sep_9
94− :: ( MonadState 1 Int m
95− , MonadState 2 Int m
96− , MonadState 3 Int m
97− , MonadState 4 Int m
98− , MonadState 5 Int m
99− , MonadState 6 Int m
100− , MonadState 7 Int m
101− , MonadState 8 Int m
102− , MonadState 9 Int m )
103− => m ()
104−stateCombinerEther_sep_9 = do
105− modify @1 id'
106− modify @2 id'
107− modify @3 id'
108− modify @4 id'
109− modify @5 id'
110− modify @6 id'
111− modify @7 id'
112− modify @8 id'
113− modify @9 id'
114− rnf <$> sequenceA
115− [ get @1
116− , get @2
117− , get @3
118− , get @4
119− , get @5
120− , get @6
121− , get @7
122− , get @8
123− , get @9 ]
124−{-# NOINLINE stateCombinerEther_sep_9 #-}
125−
126−run_readerCombinerEther_nested_9 :: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> ()
127−run_readerCombinerEther_nested_9
128− (a1, a2, a3, a4, a5, a6, a7, a8, a9)
129− = flip (runReader @9) a1
130− . flip (runReaderT @8) a2
131− . flip (runReaderT @7) a3
132− . flip (runReaderT @6) a4
133− . flip (runReaderT @5) a5
134− . flip (runReaderT @4) a6
135− . flip (runReaderT @3) a7
136− . flip (runReaderT @2) a8
137− . flip (runReaderT @1) a9
138− $ readerCombinerEther_sep_9
139−
140−run_readerCombinerEther_flatten_9 :: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> ()
141−run_readerCombinerEther_flatten_9
142− (a1, a2, a3, a4, a5, a6, a7, a8, a9)
143− =
144− runReaders
145− readerCombinerEther_sep_9
146− ( Tagged @1 a9,
147− Tagged @2 a8,
148− Tagged @3 a7,
149− Tagged @4 a6,
150− Tagged @5 a5,
151− Tagged @6 a4,
152− Tagged @7 a3,
153− Tagged @8 a2,
154− Tagged @9 a1 )
155−
156−run_readerCombinerEther_flattenhalf_9 :: (Int, Int, Int, Int, Int, Int, Int, Int, Int) -> ()
157−run_readerCombinerEther_flattenhalf_9
158− (a1, a2, a3, a4, a5, a6, a7, a8, a9) =
159− flip runReaders
160− ( Tagged @1 a9,
161− Tagged @2 a8,
162− Tagged @3 a7,
163− Tagged @4 a6 ) .
164− flip runReadersT
165− ( Tagged @5 a5,
166− Tagged @6 a4,
167− Tagged @7 a3,
168− Tagged @8 a2,
169− Tagged @9 a1 ) $
170− readerCombinerEther_sep_9
171−
172−run_stateCombinerEther_flatten_9 ::
173− (Int, Int, Int, Int, Int, Int, Int, Int, Int) ->
174− ((), _)
175−run_stateCombinerEther_flatten_9
176− (a1, a2, a3, a4, a5, a6, a7, a8, a9)
177− =
178− runStates
179− stateCombinerEther_sep_9
180− ( Tagged @1 a9,
181− Tagged @2 a8,
182− Tagged @3 a7,
183− Tagged @4 a6,
184− Tagged @5 a5,
185− Tagged @6 a4,
186− Tagged @7 a3,
187− Tagged @8 a2,
188− Tagged @9 a1 )
189−
190−tuple_9 :: (Int, Int, Int, Int, Int, Int, Int, Int, Int)
191−tuple_9 = (1, -2, 3, -4, 5, -6, 7, -8, 9)
192−
193−main :: IO ()
194−main = do
195− defaultMain
196− [ bench "readerCombinerMTL_flat_9" $ nf run_readerCombinerMTL_flat_9 tuple_9
197− , bench "readerCombinerEther_nested_9" $ nf run_readerCombinerEther_nested_9 tuple_9
198− , bench "readerCombinerEther_flatten_9" $ nf run_readerCombinerEther_flatten_9 tuple_9
199− , bench "readerCombinerEther_flattenhalf_9" $
200− nf run_readerCombinerEther_flattenhalf_9 tuple_9
201− , bench "stateCombinerMTL_flat_9" $ nf run_stateCombinerMTL_flat_9 tuple_9
202− , bench "stateCombinerEther_flatten_9" $ nf run_stateCombinerEther_flatten_9 tuple_9
203− ]
bench/TupleInstances.hsdeleted−9
@@ -1,9 +0,0 @@
1−{-# OPTIONS -fno-warn-orphans #-}
2−{-# LANGUAGE CPP #-}
3−
4−module TupleInstances () where
5−
6−#ifdef DISABLE_TUP_INSTANCES
7−import Ether.Internal (makeTupleInstancesHasLens)
8−makeTupleInstancesHasLens [4,5,9]
9−#endif
ether.cabal+53−220
@@ -1,237 +1,70 @@
1−cabal-version: 2.2
21name: ether
3−version: 0.5.2.0
2+version: 0.1.0.0
43synopsis: Monad transformers and classes
5−description: Lib
6−license: BSD-3-Clause
7−-- ^ unfortunately have to change this line due to the issue with cabal2nix
8−license-file: LICENSE
4+description:
5+ Ether is a Haskell library that extends @mtl@ and @transformers@ with
6+ tagged monad transformers and classes in a compatible way.
7+
98category: Control
10−author: Vladislav Zavialov
11−maintainer: Vladislav Zavialov <vlad.z.4096@gmail.com>
9+license: BSD3
10+license-file: LICENSE
11+author: Index Int
12+maintainer: Index Int <vlad.z.4096@gmail.com>
1213homepage: https://int-index.github.io/ether/
1314bug-reports: https://github.com/int-index/ether/issues
1415build-type: Simple
15−extra-source-files: CHANGELOG.md
16+cabal-version: >=1.22
1617
1718source-repository head
1819
19− type: git
20− location: git@github.com:int-index/ether.git
21−
22−
23−flag disable-tup-instances
20+ type: git
21+ location: git@github.com:int-index/ether.git
2422
25− description:
26− Disable auto-generated 'HasLens' instances for tuples. The reason one
27− might want to do this is to reduce the size of .hi-files, as well as the
28− time and memory GHC needs to build Ether. To recover flattening with
29− tuples, use 'Ether.Internal.makeTupleInstancesHasLens' at specific tuple
30− sizes you need in your application.
31−
32− This is a build-time performance hack, enable this flag at your own risk.
33−
34− default: False
35− manual: True
3623
3724library
3825
39− exposed-modules:
40− Ether
41− Ether.Reader
42− Ether.State
43− Ether.Writer
44− Ether.Except
45− Ether.TaggedTrans
46− Ether.TagDispatch
47− Ether.Internal
48−
49− other-modules:
50− Ether.Internal.Tags
51− Ether.Internal.HasLens
52− Ether.Internal.TH_Utils
53− Ether.Internal.TH_TupleInstances
54− Ether.Internal.TupleInstances
55−
56− build-depends:
57− base >=4.9 && <4.13,
58− transformers >=0.5.2.0,
59− transformers-lift >=0.2.0.1,
60− mtl >=2.2.2,
61− mmorph >=1.0.4,
62− monad-control >=1.0.0.4,
63− transformers-base >=0.4.4,
64− writer-cps-mtl >= 0.1.1.4,
65− exceptions >=0.8,
66− template-haskell >=2.11,
67− tagged >=0.8.5,
68− reflection >=2.1
26+ exposed-modules: Control.Ether.Tags
27+ Control.Ether.TH
28+ Control.Ether.Wrapped
29+ Control.Monad.Trans.Ether.Reader
30+ Control.Monad.Trans.Ether.Writer
31+ Control.Monad.Trans.Ether.State
32+ Control.Monad.Trans.Ether.Except
33+ Control.Monad.Ether.Reader
34+ Control.Monad.Ether.Writer
35+ Control.Monad.Ether.State
36+ Control.Monad.Ether.Except
37+ Control.Monad.Ether.Implicit.Reader
38+ Control.Monad.Ether.Implicit.Writer
39+ Control.Monad.Ether.Implicit.State
40+ Control.Monad.Ether.Implicit.Except
41+ Control.Monad.Ether.Implicit.Except.TH
42+
43+ other-modules: Control.Ether.Util
44+
45+ build-depends: base >=4.8 && <4.9
46+ , transformers >=0.4.0.3
47+ , mtl >=2.2.1
48+ , template-haskell >=2.10
49+ , newtype-generics >=0.4.1
50+
51+ hs-source-dirs: src
52+ default-language: Haskell2010
53+ ghc-options: -Wall
6954
70− default-language:
71− Haskell2010
72−
73− default-extensions:
74− AllowAmbiguousTypes
75− ConstraintKinds
76− DataKinds
77− DeriveGeneric
78− EmptyDataDecls
79− FlexibleContexts
80− FlexibleInstances
81− FunctionalDependencies
82− GADTs
83− GeneralizedNewtypeDeriving
84− PartialTypeSignatures
85− PolyKinds
86− ScopedTypeVariables
87− RankNTypes
88− TemplateHaskell
89− TupleSections
90− TypeApplications
91− TypeFamilies
92− TypeInType
93− TypeOperators
94− TypeSynonymInstances
95− UndecidableInstances
96− UndecidableSuperClasses
97−
98− hs-source-dirs:
99− src
100−
101− ghc-options:
102− -Wall -O2
103−
104− if flag(disable-tup-instances)
105− cpp-options: -DDISABLE_TUP_INSTANCES
10655
10756test-suite regression
10857
109− build-depends:
110− base >=4.9 && <4.13,
111− transformers >=0.4.2,
112− mtl >=2.2.1,
113− tasty >=0.10,
114− tasty-quickcheck >=0.8,
115− QuickCheck >=2.8,
116− ghc-prim >=0.3,
117− lens >=4.14,
118− ether
119−
120− main-is:
121− Regression.hs
122−
123− other-modules:
124− TupleInstances
125− Regression.T1
126− Regression.T2
127− Regression.T3
128− Regression.T4
129− Regression.T5
130− Regression.T6
131− Regression.T7
132− Regression.T8
133− Regression.T9
134− Regression.T10
135− Regression.T11
136− Regression.T12
137−
138− type:
139− exitcode-stdio-1.0
140−
141− hs-source-dirs:
142− test
143−
144− default-language:
145− Haskell2010
146−
147− default-extensions:
148− AllowAmbiguousTypes
149− ConstraintKinds
150− DataKinds
151− DeriveGeneric
152− EmptyDataDecls
153− FlexibleContexts
154− FlexibleInstances
155− FunctionalDependencies
156− GADTs
157− GeneralizedNewtypeDeriving
158− PartialTypeSignatures
159− PolyKinds
160− ScopedTypeVariables
161− RankNTypes
162− TemplateHaskell
163− TupleSections
164− TypeApplications
165− TypeFamilies
166− TypeInType
167− TypeOperators
168− TypeSynonymInstances
169− UndecidableInstances
170− UndecidableSuperClasses
171−
172− ghc-options:
173− -Wall -fno-warn-missing-signatures
174−
175− if flag(disable-tup-instances)
176− cpp-options: -DDISABLE_TUP_INSTANCES
177−
178−
179−benchmark bench
180−
181− build-depends:
182− base >=4.9 && <4.13,
183− mtl >=2.2.1,
184− transformers >=0.4.2,
185− criterion >=1.1,
186− deepseq >=1.4,
187− lens >=4.14,
188− ether
189−
190− main-is:
191− Bench.hs
192−
193− other-modules:
194− TupleInstances
195−
196− type:
197− exitcode-stdio-1.0
198−
199− hs-source-dirs:
200− bench
201−
202− default-language:
203− Haskell2010
204−
205− default-extensions:
206− AllowAmbiguousTypes
207− ConstraintKinds
208− DataKinds
209− DeriveGeneric
210− EmptyDataDecls
211− FlexibleContexts
212− FlexibleInstances
213− FunctionalDependencies
214− GADTs
215− GeneralizedNewtypeDeriving
216− PartialTypeSignatures
217− PolyKinds
218− ScopedTypeVariables
219− RankNTypes
220− TemplateHaskell
221− TupleSections
222− TypeApplications
223− TypeFamilies
224− TypeInType
225− TypeOperators
226− TypeSynonymInstances
227− UndecidableInstances
228− UndecidableSuperClasses
229−
230− ghc-options:
231− -Wall -O2
232−
233− ghc-prof-options:
234− -fprof-auto
235−
236− if flag(disable-tup-instances)
237− cpp-options: -DDISABLE_TUP_INSTANCES
58+ build-depends: base >=4.8 && <4.9
59+ , transformers >=0.4.0.3
60+ , mtl >=2.2.1
61+ , tasty >=0.10
62+ , tasty-quickcheck >=0.8
63+ , QuickCheck >=2.8
64+ , ether
65+
66+ main-is: Regression.hs
67+ type: exitcode-stdio-1.0
68+ hs-source-dirs: test
69+ default-language: Haskell2010
70+ ghc-options: -Wall
shell.nixdeleted−22
@@ -1,22 +0,0 @@
1−{ pkgs ? import <nixpkgs> {},
2− hc ? "ghc844"
3−}:
4−
5−pkgs.stdenv.mkDerivation rec {
6− name = "ether";
7− buildInputs = [
8− pkgs.haskell.compiler.${hc}
9− pkgs.git
10− pkgs.zlib
11− pkgs.cabal-install
12− pkgs.pkgconfig
13− ];
14− shellHook = ''
15− export LD_LIBRARY_PATH=${pkgs.lib.makeLibraryPath buildInputs}:$LD_LIBRARY_PATH
16− export LANG=en_US.UTF-8
17− '';
18− LOCALE_ARCHIVE =
19− if pkgs.stdenv.isLinux
20− then "${pkgs.glibcLocales}/lib/locale/locale-archive"
21− else "";
22−}
src/Control/Ether/TH.hsnew file+47
@@ -0,0 +1,47 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+module Control.Ether.TH
3+ ( ethereal
4+ , fmapN
5+ , deepN
6+ ) where
7+
8+import qualified Language.Haskell.TH as TH
9+
10+import Data.Proxy
11+
12+emptyDataDecl :: TH.Name -> TH.DecQ
13+emptyDataDecl name = TH.dataD (return []) name [] [] []
14+
15+funSimple :: TH.Name -> TH.ExpQ -> TH.DecQ
16+funSimple name body = TH.funD name [ TH.clause [] (TH.normalB body) [] ]
17+
18+proxySimple :: TH.Name -> TH.TypeQ -> TH.Q (TH.Dec, TH.Dec)
19+proxySimple name ty = do
20+ sig <- TH.sigD name [t| Proxy $ty |]
21+ val <- funSimple name [e| Proxy |]
22+ return (sig, val)
23+
24+-- |
25+-- Creates a tag and a value-level proxy for it.
26+--
27+-- @'ethereal' \"Foo\" \"foo\"@ generates the following code:
28+--
29+-- > data Foo
30+-- > foo :: Proxy Foo
31+-- > foo = Proxy
32+ethereal :: String -> String -> TH.DecsQ
33+ethereal strTagName strTagProxyName = do
34+ let tagName = TH.mkName strTagName
35+ tag = TH.conT tagName
36+ tagProxyName = TH.mkName strTagProxyName
37+ tagDecl <- emptyDataDecl tagName
38+ (tagProxySig, tagProxyVal) <- proxySimple tagProxyName tag
39+ return [tagDecl, tagProxySig, tagProxyVal]
40+
41+fmapN :: Int -> TH.ExpQ
42+fmapN 0 = [|id|]
43+fmapN n = TH.infixApp [|fmap|] [|(.)|] (fmapN (n - 1))
44+
45+deepN :: Int -> TH.ExpQ -> TH.ExpQ
46+deepN 0 _ = [|id|]
47+deepN n f = [| $(fmapN n) $f $(deepN (n-1) f) |]
src/Control/Ether/Tags.hsnew file+155
@@ -0,0 +1,155 @@
1+{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE PolyKinds #-}
4+{-# LANGUAGE ConstraintKinds #-}
5+{-# LANGUAGE TypeOperators #-}
6+{-# LANGUAGE FlexibleInstances #-}
7+{-# LANGUAGE FlexibleContexts #-}
8+{-# LANGUAGE UndecidableInstances #-}
9+{-# LANGUAGE MultiParamTypeClasses #-}
10+{-# LANGUAGE FunctionalDependencies #-}
11+{-# LANGUAGE DefaultSignatures #-}
12+module Control.Ether.Tags
13+ ( Taggable(..)
14+ , Tagged(..)
15+ , Tags
16+ , Inners
17+ , UniqueTag
18+ , UniqueTags
19+ , ensureUniqueTags
20+ ) where
21+
22+import Data.Proxy (Proxy)
23+import Data.Functor.Identity (Identity)
24+import Data.Monoid (First, Last)
25+import qualified Control.Monad.ST.Strict as Strict (ST)
26+import qualified Control.Monad.ST.Lazy as Lazy (ST)
27+import GHC.Conc (STM)
28+import GHC.Exts (Constraint)
29+import qualified Control.Newtype as NT
30+import Control.Ether.Util (type (++), MaybeToList)
31+
32+import qualified Control.Monad.Trans.Cont as Trans
33+import qualified Control.Monad.Trans.Except as Trans
34+import qualified Control.Monad.Trans.Identity as Trans
35+import qualified Control.Monad.Trans.List as Trans
36+import qualified Control.Monad.Trans.Maybe as Trans
37+import qualified Control.Monad.Trans.Reader as Trans
38+import qualified Control.Monad.Trans.State.Lazy as Trans.Lazy
39+import qualified Control.Monad.Trans.State.Strict as Trans.Strict
40+import qualified Control.Monad.Trans.Writer.Lazy as Trans.Lazy
41+import qualified Control.Monad.Trans.Writer.Strict as Trans.Strict
42+
43+-- |
44+-- The main purpose of the 'UniqueTag' class is to provide clear error
45+-- messages when the tag uniqueness property is violated. You should never
46+-- provide instances for it unless you know what you're doing.
47+class UniqueTag a
48+
49+type family IsUnique (x :: k) (as :: [k]) :: Constraint where
50+ IsUnique x (x ': as) = UniqueTag x
51+ IsUnique x (a ': as) = IsUnique x as
52+ IsUnique x '[] = ()
53+
54+type family Unique (as :: [k]) :: Constraint where
55+ Unique '[] = ()
56+ Unique (a ': as) = (IsUnique a as, Unique as)
57+
58+-- |
59+-- The 'UniqueTags` constraint placed on a type variable representing a
60+-- monad transformer stack ensures that every tag in the stack appears
61+-- only once.
62+type family UniqueTags (m :: * -> *) :: Constraint where
63+ UniqueTags m = Unique (Tags m)
64+
65+-- |
66+-- Type-restricted version of 'id' that adds a 'UniqueTags' constraint to
67+-- the provided monadic value.
68+ensureUniqueTags :: UniqueTags m => m a -> m a
69+ensureUniqueTags = id
70+
71+type family ListMapTag (as :: [* -> *]) :: [*] where
72+ ListMapTag '[] = '[]
73+ ListMapTag (a ': as) = MaybeToList (Tag a) ++ ListMapTag as
74+
75+-- | The 'Taggable' class defines the type families to manage tags in monad
76+-- transformer stacks. Its kind is restricted to @* -> *@ to prevent incorrect
77+-- instances.
78+class Taggable (m :: * -> *) where
79+
80+ -- | The 'Tag' type family equals @Nothing@ for most types, but for tagged
81+ -- monad transformers it equals @Just tag@.
82+ type Tag m :: Maybe *
83+ type instance Tag m = 'Nothing
84+
85+ -- | The 'Inner' type family equals @Nothing@ for most types, but for
86+ -- monad transformers with inner monad @m@ it equals @Just m@.
87+ type Inner m :: Maybe (* -> *)
88+ type instance Inner m = 'Nothing
89+
90+type family Inners' m where
91+ Inners' 'Nothing = '[]
92+ Inners' ('Just n) = n ': Inners n
93+
94+type Inners m = Inners' (Inner m)
95+
96+instance Taggable IO
97+instance Taggable Identity
98+
99+instance Taggable Maybe
100+instance Taggable Last
101+instance Taggable First
102+instance Taggable ((->) r)
103+instance Taggable STM
104+instance Taggable (Either e)
105+instance Taggable Proxy
106+instance Taggable (Strict.ST s)
107+instance Taggable (Lazy.ST s)
108+
109+instance Taggable (Trans.ContT r m) where
110+ type Inner (Trans.ContT r m) = 'Just m
111+
112+instance Taggable (Trans.ExceptT e m) where
113+ type Inner (Trans.ExceptT e m) = 'Just m
114+
115+instance Taggable (Trans.IdentityT m) where
116+ type Inner (Trans.IdentityT m) = 'Just m
117+
118+instance Taggable (Trans.ListT m) where
119+ type Inner (Trans.ListT m) = 'Just m
120+
121+instance Taggable (Trans.MaybeT m) where
122+ type Inner (Trans.MaybeT m) = 'Just m
123+
124+instance Taggable (Trans.ReaderT r m) where
125+ type Inner (Trans.ReaderT r m) = 'Just m
126+
127+instance Taggable (Trans.Lazy.StateT s m) where
128+ type Inner (Trans.Lazy.StateT s m) = 'Just m
129+
130+instance Taggable (Trans.Strict.StateT s m) where
131+ type Inner (Trans.Strict.StateT s m) = 'Just m
132+
133+instance Taggable (Trans.Lazy.WriterT w m) where
134+ type Inner (Trans.Lazy.WriterT w m) = 'Just m
135+
136+instance Taggable (Trans.Strict.WriterT w m) where
137+ type Inner (Trans.Strict.WriterT w m) = 'Just m
138+
139+-- | The 'Tags' type function returns a type-level list of all tags in
140+-- a monad transformer stack. Requires 'Taggable' instances.
141+type Tags (m :: * -> *) = MaybeToList (Tag m) ++ ListMapTag (Inners m)
142+
143+-- | The 'Tagged' type class establishes a relationship between a tagged
144+-- monad transformer and its untagged counterpart.
145+class (Taggable m, Tag m ~ 'Just tag) => Tagged m tag | m -> tag where
146+
147+ type Untagged m :: * -> *
148+
149+ tagged :: proxy tag -> Untagged m a -> m a
150+ default tagged :: NT.Newtype (m a) => proxy tag -> NT.O (m a) -> m a
151+ tagged _ = NT.pack
152+
153+ untagged :: proxy tag -> m a -> Untagged m a
154+ default untagged :: NT.Newtype (m a) => proxy tag -> m a -> NT.O (m a)
155+ untagged _ = NT.unpack
src/Control/Ether/Util.hsnew file+37
@@ -0,0 +1,37 @@
1+{-# LANGUAGE DataKinds, PolyKinds #-}
2+{-# LANGUAGE TypeOperators #-}
3+{-# LANGUAGE TypeFamilies #-}
4+module Control.Ether.Util
5+ ( liftCatch_ExceptT
6+ , liftListen_WriterT
7+ , liftPass_WriterT
8+ , type (++)
9+ , MaybeToList
10+ ) where
11+
12+import qualified Control.Monad.Signatures as Sig
13+import qualified Control.Monad.Trans.Except as Trans
14+import qualified Control.Monad.Trans.Writer as Trans
15+
16+type family (as :: [*]) ++ (bs :: [*]) :: [*] where
17+ '[] ++ bs = bs
18+ (a ': as) ++ bs = a ': (as ++ bs)
19+
20+type family MaybeToList (mt :: Maybe k) :: [k] where
21+ MaybeToList 'Nothing = '[]
22+ MaybeToList ('Just t) = '[t]
23+
24+liftCatch_ExceptT :: Sig.Catch e m (Either e' a) -> Sig.Catch e (Trans.ExceptT e' m) a
25+liftCatch_ExceptT catchE m h = Trans.ExceptT $ catchE (Trans.runExceptT m) (Trans.runExceptT . h)
26+
27+-- TODO: Not sure if correct
28+liftListen_WriterT :: Monad m => Sig.Listen w' m (a, w) -> Sig.Listen w' (Trans.WriterT w m) a
29+liftListen_WriterT listen m = Trans.WriterT $ do
30+ ~((a, w'), w) <- listen (Trans.runWriterT m)
31+ return ((a, w), w')
32+
33+-- TODO: Not sure if correct
34+liftPass_WriterT :: Monad m => Sig.Pass w' m (a, w) -> Sig.Pass w' (Trans.WriterT w m) a
35+liftPass_WriterT pass m = Trans.WriterT $ pass $ do
36+ ~((a, f), w) <- Trans.runWriterT m
37+ return ((a, w), f)
src/Control/Ether/Wrapped.hsnew file+39
@@ -0,0 +1,39 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE FlexibleInstances #-}
3+{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE UndecidableInstances #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
6+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7+module Control.Ether.Wrapped where
8+
9+import Data.Proxy (Proxy(Proxy))
10+import Control.Applicative (Alternative)
11+import Control.Monad (MonadPlus)
12+import Control.Monad.Fix (MonadFix)
13+import Control.Monad.IO.Class (MonadIO)
14+import Control.Monad.Ether.Reader
15+import Control.Monad.Ether.State
16+import Control.Monad.Ether.Except
17+
18+import qualified Control.Monad.Reader as Class
19+import qualified Control.Monad.State as Class
20+import qualified Control.Monad.Except as Class
21+
22+newtype WrappedEther tag m a = WrapEther { unwrapEther :: m a }
23+ deriving ( Functor, Applicative, Alternative, Monad, MonadPlus
24+ , MonadFix, MonadIO )
25+
26+instance MonadReader tag r m => Class.MonadReader r (WrappedEther tag m) where
27+ ask = WrapEther $ ask (Proxy :: Proxy tag)
28+ local f = WrapEther . local (Proxy :: Proxy tag) f . unwrapEther
29+
30+instance MonadState tag s m => Class.MonadState s (WrappedEther tag m) where
31+ get = WrapEther $ get (Proxy :: Proxy tag)
32+ put = WrapEther . put (Proxy :: Proxy tag)
33+
34+instance MonadExcept tag e m => Class.MonadError e (WrappedEther tag m) where
35+ throwError = WrapEther . throw (Proxy :: Proxy tag)
36+ catchError m h = WrapEther $ catch (Proxy :: Proxy tag) (unwrapEther m) (unwrapEther . h)
37+
38+ethered :: proxy tag -> WrappedEther tag m a -> m a
39+ethered _proxy = unwrapEther
src/Control/Monad/Ether/Except.hsnew file+116
@@ -0,0 +1,116 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE UndecidableInstances #-}
6+{-# LANGUAGE DataKinds #-}
7+{-# LANGUAGE ConstraintKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE FunctionalDependencies #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE RankNTypes #-}
12+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
13+module Control.Monad.Ether.Except
14+ (
15+ -- * MonadExcept class
16+ MonadExcept(..)
17+ -- * The Except monad
18+ , Except
19+ , runExcept
20+ -- * The ExceptT monad transformer
21+ , ExceptT
22+ , exceptT
23+ , runExceptT
24+ , mapExceptT
25+ ) where
26+
27+import Data.Proxy (Proxy(Proxy))
28+import Control.Monad.Trans (lift)
29+
30+import Control.Monad.Trans.Ether.Except hiding (throw, catch)
31+import qualified Control.Monad.Trans.Ether.Except as E
32+import qualified Control.Monad.Trans.Ether.Reader as R
33+import qualified Control.Monad.Trans.Ether.Writer as W
34+import qualified Control.Monad.Trans.Ether.State as S
35+import qualified Control.Ether.Util as Util
36+
37+-- for mtl instances
38+import qualified Control.Monad.Trans.Except as Trans.E
39+import qualified Control.Monad.Trans.Identity as Trans.I
40+import qualified Control.Monad.Trans.List as Trans.L
41+import qualified Control.Monad.Trans.Maybe as Trans.M
42+import qualified Control.Monad.Trans.Reader as Trans.R
43+import qualified Control.Monad.Trans.State.Lazy as Trans.S.Lazy
44+import qualified Control.Monad.Trans.State.Strict as Trans.S.Strict
45+import qualified Control.Monad.Trans.Writer.Lazy as Trans.W.Lazy
46+import qualified Control.Monad.Trans.Writer.Strict as Trans.W.Strict
47+
48+class Monad m => MonadExcept tag e m | m tag -> e where
49+
50+ -- | Is used within a monadic computation to begin exception processing.
51+ throw :: proxy tag -> e -> m a
52+
53+ -- | A handler function to handle previous exceptions and return to
54+ -- normal execution.
55+ catch :: proxy tag -> m a -> (e -> m a) -> m a
56+
57+instance {-# OVERLAPPING #-} Monad m => MonadExcept tag e (ExceptT tag e m) where
58+ throw = E.throw
59+ catch = E.catch
60+
61+instance MonadExcept tag e m => MonadExcept tag e (ExceptT tag' e' m) where
62+ throw t = lift . throw t
63+ catch t = liftCatch Proxy (catch t)
64+
65+-- Instances for other tagged transformers
66+
67+instance MonadExcept tag e m => MonadExcept tag e (R.ReaderT tag' r m) where
68+ throw t = lift . throw t
69+ catch t = R.liftCatch Proxy (catch t)
70+
71+instance (Monoid w, MonadExcept tag e m) => MonadExcept tag e (W.WriterT tag' w m) where
72+ throw t = lift . throw t
73+ catch t = W.liftCatch Proxy (catch t)
74+
75+instance MonadExcept tag e m => MonadExcept tag e (S.StateT tag' s m) where
76+ throw t = lift . throw t
77+ catch t = S.liftCatch Proxy (catch t)
78+
79+
80+-- Instances for mtl transformers
81+
82+instance MonadExcept tag e m => MonadExcept tag e (Trans.E.ExceptT e' m) where
83+ throw t = lift . throw t
84+ catch t = Util.liftCatch_ExceptT (catch t)
85+
86+instance MonadExcept tag e m => MonadExcept tag e (Trans.I.IdentityT m) where
87+ throw t = lift . throw t
88+ catch t = Trans.I.liftCatch (catch t)
89+
90+instance MonadExcept tag e m => MonadExcept tag e (Trans.L.ListT m) where
91+ throw t = lift . throw t
92+ catch t = Trans.L.liftCatch (catch t)
93+
94+instance MonadExcept tag e m => MonadExcept tag e (Trans.M.MaybeT m) where
95+ throw t = lift . throw t
96+ catch t = Trans.M.liftCatch (catch t)
97+
98+instance MonadExcept tag e m => MonadExcept tag e (Trans.R.ReaderT r m) where
99+ throw t = lift . throw t
100+ catch t = Trans.R.liftCatch (catch t)
101+
102+instance MonadExcept tag e m => MonadExcept tag e (Trans.S.Lazy.StateT s m) where
103+ throw t = lift . throw t
104+ catch t = Trans.S.Lazy.liftCatch (catch t)
105+
106+instance MonadExcept tag e m => MonadExcept tag e (Trans.S.Strict.StateT s m) where
107+ throw t = lift . throw t
108+ catch t = Trans.S.Strict.liftCatch (catch t)
109+
110+instance (Monoid w, MonadExcept tag e m) => MonadExcept tag e (Trans.W.Lazy.WriterT w m) where
111+ throw t = lift . throw t
112+ catch t = Trans.W.Lazy.liftCatch (catch t)
113+
114+instance (Monoid w, MonadExcept tag e m) => MonadExcept tag e (Trans.W.Strict.WriterT w m) where
115+ throw t = lift . throw t
116+ catch t = Trans.W.Strict.liftCatch (catch t)
src/Control/Monad/Ether/Implicit/Except.hsnew file+40
@@ -0,0 +1,40 @@
1+{-# LANGUAGE ConstraintKinds #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+module Control.Monad.Ether.Implicit.Except
4+ (
5+ -- * MonadExcept class
6+ MonadExcept
7+ , throw
8+ , catch
9+ -- * The Except monad
10+ , Except
11+ , runExcept
12+ -- * The ExceptT monad transformer
13+ , ExceptT
14+ , exceptT
15+ , runExceptT
16+ ) where
17+
18+import Data.Proxy
19+import qualified Control.Monad.Ether.Except as Explicit
20+
21+type MonadExcept e = Explicit.MonadExcept e e
22+
23+throw :: forall e m a . MonadExcept e m => e -> m a
24+throw = Explicit.throw (Proxy :: Proxy e)
25+
26+catch :: forall e m a . MonadExcept e m => m a -> (e -> m a) -> m a
27+catch = Explicit.catch (Proxy :: Proxy e)
28+
29+type Except e = Explicit.Except e e
30+
31+runExcept :: Except e a -> Either e a
32+runExcept = Explicit.runExcept Proxy
33+
34+type ExceptT e = Explicit.ExceptT e e
35+
36+exceptT :: m (Either e a) -> ExceptT e m a
37+exceptT = Explicit.exceptT Proxy
38+
39+runExceptT :: ExceptT e m a -> m (Either e a)
40+runExceptT = Explicit.runExceptT Proxy
src/Control/Monad/Ether/Implicit/Except/TH.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+module Control.Monad.Ether.Implicit.Except.TH (try', try) where
3+
4+import qualified Language.Haskell.TH as TH
5+import Control.Ether.TH (deepN)
6+import Control.Monad.Ether.Implicit.Except
7+
8+try' :: Functor m => ExceptT e m a -> (e -> a) -> m a
9+try' m h = either h id <$> runExceptT m
10+
11+try :: Int -> TH.ExpQ
12+try n = deepN n [|try'|]
src/Control/Monad/Ether/Implicit/Reader.hsnew file+40
@@ -0,0 +1,40 @@
1+{-# LANGUAGE ConstraintKinds #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+module Control.Monad.Ether.Implicit.Reader
4+ ( ReaderT
5+ , Reader
6+ , MonadReader
7+ , runReaderT
8+ , runReader
9+ , local
10+ , ask
11+ , reader
12+ , asks
13+ ) where
14+
15+import Data.Proxy
16+import qualified Control.Monad.Ether.Reader as Explicit
17+
18+type ReaderT r = Explicit.ReaderT r r
19+type Reader r = Explicit.Reader r r
20+
21+runReaderT :: ReaderT r m a -> r -> m a
22+runReaderT = Explicit.runReaderT Proxy
23+
24+runReader :: Reader r a -> r -> a
25+runReader = Explicit.runReader Proxy
26+
27+type MonadReader r = Explicit.MonadReader r r
28+
29+local :: forall m r a . MonadReader r m => (r -> r) -> m a -> m a
30+local = Explicit.local (Proxy :: Proxy r)
31+
32+ask :: forall m r . MonadReader r m => m r
33+ask = Explicit.ask (Proxy :: Proxy r)
34+
35+reader :: forall m r a . MonadReader r m => (r -> a) -> m a
36+reader = Explicit.reader (Proxy :: Proxy r)
37+
38+asks :: forall m r a . MonadReader r m => (r -> a) -> m a
39+asks = Explicit.asks (Proxy :: Proxy r)
40+
src/Control/Monad/Ether/Implicit/State.hsnew file+60
@@ -0,0 +1,60 @@
1+{-# LANGUAGE ConstraintKinds #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+module Control.Monad.Ether.Implicit.State
4+ ( StateT
5+ , State
6+ , runStateT
7+ , runState
8+ , evalStateT
9+ , evalState
10+ , execStateT
11+ , execState
12+ --
13+ , MonadState
14+ , get
15+ , gets
16+ , put
17+ , state
18+ , modify
19+ ) where
20+
21+import Data.Proxy
22+import qualified Control.Monad.Ether.State as Explicit
23+
24+type StateT s = Explicit.StateT s s
25+type State s = Explicit.State s s
26+
27+runStateT :: StateT s m a -> s -> m (a, s)
28+runStateT = Explicit.runStateT Proxy
29+
30+runState :: State s a -> s -> (a, s)
31+runState = Explicit.runState Proxy
32+
33+evalStateT :: Monad m => StateT s m a -> s -> m a
34+evalStateT = Explicit.evalStateT Proxy
35+
36+evalState :: State s a -> s -> a
37+evalState = Explicit.evalState Proxy
38+
39+execStateT :: Monad m => StateT s m a -> s -> m s
40+execStateT = Explicit.execStateT Proxy
41+
42+execState :: State s a -> s -> s
43+execState = Explicit.execState Proxy
44+
45+type MonadState s = Explicit.MonadState s s
46+
47+get :: forall m s . MonadState s m => m s
48+get = Explicit.get (Proxy :: Proxy s)
49+
50+gets :: forall m s a . MonadState s m => (s -> a) -> m a
51+gets = Explicit.gets (Proxy :: Proxy s)
52+
53+put :: forall m s . MonadState s m => s -> m ()
54+put = Explicit.put (Proxy :: Proxy s)
55+
56+state :: forall m s a . MonadState s m => (s -> (a, s)) -> m a
57+state = Explicit.state (Proxy :: Proxy s)
58+
59+modify :: forall m s . MonadState s m => (s -> s) -> m ()
60+modify = Explicit.modify (Proxy :: Proxy s)
src/Control/Monad/Ether/Implicit/Writer.hsnew file+64
@@ -0,0 +1,64 @@
1+{-# LANGUAGE ConstraintKinds #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+module Control.Monad.Ether.Implicit.Writer
4+ (
5+ -- * MonadWriter class
6+ MonadWriter
7+ , writer
8+ , tell
9+ , listen
10+ , pass
11+ , listens
12+ , censor
13+ -- * The Writer monad
14+ , Writer
15+ , runWriter
16+ , execWriter
17+ -- * The WriterT monad transformer
18+ , WriterT
19+ , writerT
20+ , runWriterT
21+ , execWriterT
22+ ) where
23+
24+import Data.Proxy
25+import qualified Control.Monad.Ether.Writer as Explicit
26+
27+type MonadWriter w = Explicit.MonadWriter w w
28+
29+writer :: forall m w a . MonadWriter w m => (a, w) -> m a
30+writer = Explicit.writer (Proxy :: Proxy w)
31+
32+tell :: forall m w . MonadWriter w m => w -> m ()
33+tell = Explicit.tell (Proxy :: Proxy w)
34+
35+listen :: forall m w a . MonadWriter w m => m a -> m (a, w)
36+listen = Explicit.listen (Proxy :: Proxy w)
37+
38+pass :: forall m w a . MonadWriter w m => m (a, w -> w) -> m a
39+pass = Explicit.pass (Proxy :: Proxy w)
40+
41+listens :: forall m w a b . MonadWriter w m => (w -> b) -> m a -> m (a, b)
42+listens = Explicit.listens (Proxy :: Proxy w)
43+
44+censor :: forall m w a . MonadWriter w m => (w -> w) -> m a -> m a
45+censor = Explicit.censor (Proxy :: Proxy w)
46+
47+type Writer w = Explicit.Writer w w
48+
49+runWriter :: Writer w a -> (a, w)
50+runWriter = Explicit.runWriter Proxy
51+
52+execWriter :: Writer w a -> w
53+execWriter = Explicit.execWriter Proxy
54+
55+type WriterT w = Explicit.WriterT w w
56+
57+writerT :: m (a, w) -> WriterT w m a
58+writerT = Explicit.writerT Proxy
59+
60+runWriterT :: WriterT w m a -> m (a, w)
61+runWriterT = Explicit.runWriterT Proxy
62+
63+execWriterT :: Monad m => WriterT w m a -> m w
64+execWriterT = Explicit.execWriterT Proxy
src/Control/Monad/Ether/Reader.hsnew file+146
@@ -0,0 +1,146 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE UndecidableInstances #-}
6+{-# LANGUAGE DataKinds #-}
7+{-# LANGUAGE ConstraintKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE FunctionalDependencies #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE RankNTypes #-}
12+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
13+module Control.Monad.Ether.Reader
14+ (
15+ -- * MonadReader class
16+ MonadReader(..)
17+ , asks
18+ -- * The Reader monad
19+ , Reader
20+ , runReader
21+ -- * The ReaderT monad transformer
22+ , ReaderT
23+ , readerT
24+ , runReaderT
25+ , mapReaderT
26+ ) where
27+
28+import Data.Proxy (Proxy(Proxy))
29+import Control.Monad.Trans (lift)
30+
31+import Control.Monad.Trans.Ether.Writer (WriterT, mapWriterT)
32+import Control.Monad.Trans.Ether.State (StateT , mapStateT)
33+import Control.Monad.Trans.Ether.Except (ExceptT, mapExceptT)
34+import Control.Monad.Trans.Ether.Reader hiding (reader, ask, local)
35+import qualified Control.Monad.Trans.Ether.Reader as R
36+
37+-- for mtl instances
38+import qualified Control.Monad.Trans.Cont as Trans (ContT , liftLocal)
39+import qualified Control.Monad.Trans.Except as Trans (ExceptT , mapExceptT)
40+import qualified Control.Monad.Trans.Identity as Trans (IdentityT, mapIdentityT)
41+import qualified Control.Monad.Trans.List as Trans (ListT , mapListT)
42+import qualified Control.Monad.Trans.Maybe as Trans (MaybeT , mapMaybeT)
43+import qualified Control.Monad.Trans.Reader as Trans (ReaderT , mapReaderT)
44+import qualified Control.Monad.Trans.State.Lazy as Trans.Lazy (StateT , mapStateT)
45+import qualified Control.Monad.Trans.State.Strict as Trans.Strict (StateT , mapStateT)
46+import qualified Control.Monad.Trans.Writer.Lazy as Trans.Lazy (WriterT , mapWriterT)
47+import qualified Control.Monad.Trans.Writer.Strict as Trans.Strict (WriterT , mapWriterT)
48+
49+class Monad m => MonadReader tag r m | m tag -> r where
50+
51+ {-# MINIMAL (ask | reader), local #-}
52+
53+ -- | Retrieves the monad environment.
54+ ask :: proxy tag -> m r
55+ ask t = reader t id
56+
57+ -- | Executes a computation in a modified environment.
58+ local
59+ :: proxy tag
60+ -> (r -> r)
61+ -- ^ The function to modify the environment.
62+ -> m a
63+ -- ^ @Reader@ to run in the modified environment.
64+ -> m a
65+
66+ -- | Retrieves a function of the current environment.
67+ reader
68+ :: proxy tag
69+ -> (r -> a)
70+ -- ^ The selector function to apply to the environment.
71+ -> m a
72+ reader t f = fmap f (ask t)
73+
74+-- | Retrieves a function of the current environment.
75+asks
76+ :: MonadReader tag r m
77+ => proxy tag
78+ -> (r -> a)
79+ -- ^ The selector function to apply to the environment.
80+ -> m a
81+asks = reader
82+
83+instance {-# OVERLAPPING #-} Monad m => MonadReader tag r (ReaderT tag r m) where
84+ ask = R.ask
85+ local = R.local
86+ reader = R.reader
87+
88+instance MonadReader tag r m => MonadReader tag r (ReaderT tag' r' m) where
89+ ask t = lift (ask t)
90+ local t = mapReaderT Proxy . local t
91+
92+-- Instances for other tagged transformers
93+
94+instance (Monoid w, MonadReader tag r m) => MonadReader tag r (WriterT tag' w m) where
95+ ask t = lift (ask t)
96+ local t = mapWriterT Proxy . local t
97+
98+instance (MonadReader tag r m) => MonadReader tag r (StateT tag' s m) where
99+ ask t = lift (ask t)
100+ local t = mapStateT Proxy . local t
101+
102+instance (MonadReader tag r m) => MonadReader tag r (ExceptT tag' e m) where
103+ ask t = lift (ask t)
104+ local t = mapExceptT Proxy . local t
105+
106+-- Instances for mtl transformers
107+
108+instance MonadReader tag r m => MonadReader tag r (Trans.ContT r' m) where
109+ ask t = lift (ask t)
110+ local t = Trans.liftLocal (ask t) (local t)
111+
112+instance MonadReader tag r m => MonadReader tag r (Trans.ExceptT e m) where
113+ ask t = lift (ask t)
114+ local t = Trans.mapExceptT . local t
115+
116+instance MonadReader tag r m => MonadReader tag r (Trans.IdentityT m) where
117+ ask t = lift (ask t)
118+ local t = Trans.mapIdentityT . local t
119+
120+instance MonadReader tag r m => MonadReader tag r (Trans.ListT m) where
121+ ask t = lift (ask t)
122+ local t = Trans.mapListT . local t
123+
124+instance MonadReader tag r m => MonadReader tag r (Trans.MaybeT m) where
125+ ask t = lift (ask t)
126+ local t = Trans.mapMaybeT . local t
127+
128+instance MonadReader tag r m => MonadReader tag r (Trans.ReaderT r' m) where
129+ ask t = lift (ask t)
130+ local t = Trans.mapReaderT . local t
131+
132+instance MonadReader tag r m => MonadReader tag r (Trans.Lazy.StateT s m) where
133+ ask t = lift (ask t)
134+ local t = Trans.Lazy.mapStateT . local t
135+
136+instance MonadReader tag r m => MonadReader tag r (Trans.Strict.StateT s m) where
137+ ask t = lift (ask t)
138+ local t = Trans.Strict.mapStateT . local t
139+
140+instance (Monoid w, MonadReader tag r m) => MonadReader tag r (Trans.Lazy.WriterT w m) where
141+ ask t = lift (ask t)
142+ local t = Trans.Lazy.mapWriterT . local t
143+
144+instance (Monoid w, MonadReader tag r m) => MonadReader tag r (Trans.Strict.WriterT w m) where
145+ ask t = lift (ask t)
146+ local t = Trans.Strict.mapWriterT . local t
src/Control/Monad/Ether/State.hsnew file+158
@@ -0,0 +1,158 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE UndecidableInstances #-}
6+{-# LANGUAGE DataKinds #-}
7+{-# LANGUAGE ConstraintKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE FunctionalDependencies #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE RankNTypes #-}
12+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
13+module Control.Monad.Ether.State
14+ (
15+ -- * MonadState class
16+ MonadState(..)
17+ , modify
18+ , gets
19+ -- * The State monad
20+ , State
21+ , runState
22+ , evalState
23+ , execState
24+ -- * The StateT monad transformer
25+ , StateT
26+ , stateT
27+ , runStateT
28+ , evalStateT
29+ , execStateT
30+ , mapStateT
31+ ) where
32+
33+import Control.Monad.Trans (lift)
34+
35+import Control.Monad.Trans.Ether.Reader (ReaderT)
36+import Control.Monad.Trans.Ether.Writer (WriterT)
37+import Control.Monad.Trans.Ether.Except (ExceptT)
38+import Control.Monad.Trans.Ether.State hiding (state, get, put)
39+import qualified Control.Monad.Trans.Ether.State as S
40+
41+-- for mtl instances
42+import qualified Control.Monad.Trans.Cont as Trans (ContT)
43+import qualified Control.Monad.Trans.Except as Trans (ExceptT)
44+import qualified Control.Monad.Trans.Identity as Trans (IdentityT)
45+import qualified Control.Monad.Trans.List as Trans (ListT)
46+import qualified Control.Monad.Trans.Maybe as Trans (MaybeT)
47+import qualified Control.Monad.Trans.Reader as Trans (ReaderT)
48+import qualified Control.Monad.Trans.State.Lazy as Trans.Lazy (StateT)
49+import qualified Control.Monad.Trans.State.Strict as Trans.Strict (StateT)
50+import qualified Control.Monad.Trans.Writer.Lazy as Trans.Lazy (WriterT)
51+import qualified Control.Monad.Trans.Writer.Strict as Trans.Strict (WriterT)
52+
53+class Monad m => MonadState tag s m | m tag -> s where
54+
55+ {-# MINIMAL state | get, put #-}
56+
57+ -- | Return the state from the internals of the monad.
58+ get :: proxy tag -> m s
59+ get t = state t (\s -> (s, s))
60+
61+ -- | Replace the state inside the monad.
62+ put :: proxy tag -> s -> m ()
63+ put t s = state t (\_ -> ((), s))
64+
65+ -- | Embed a simple state action into the monad.
66+ state :: proxy tag -> (s -> (a, s)) -> m a
67+ state t f = do
68+ s <- get t
69+ let ~(a, s') = f s
70+ put t s'
71+ return a
72+
73+-- | Modifies the state inside a state monad.
74+modify :: MonadState tag s m => proxy tag -> (s -> s) -> m ()
75+modify t f = state t (\s -> ((), f s))
76+
77+-- | Gets specific component of the state, using a projection function supplied.
78+gets :: MonadState tag s m => proxy tag -> (s -> a) -> m a
79+gets t f = fmap f (get t)
80+
81+instance {-# OVERLAPPING #-} Monad m => MonadState tag s (StateT tag s m) where
82+ get = S.get
83+ put = S.put
84+ state = S.state
85+
86+instance MonadState tag s m => MonadState tag s (StateT tag' s' m) where
87+ get t = lift (get t)
88+ put t = lift . put t
89+ state t = lift . state t
90+
91+-- Instances for other tagged transformers
92+
93+instance (MonadState tag s m) => MonadState tag s (ReaderT tag' r m) where
94+ get t = lift (get t)
95+ put t = lift . put t
96+ state t = lift . state t
97+
98+instance (Monoid w, MonadState tag s m) => MonadState tag s (WriterT tag' w m) where
99+ get t = lift (get t)
100+ put t = lift . put t
101+ state t = lift . state t
102+
103+instance (MonadState tag s m) => MonadState tag s (ExceptT tag' e m) where
104+ get t = lift (get t)
105+ put t = lift . put t
106+ state t = lift . state t
107+
108+-- Instances for mtl transformers
109+
110+instance MonadState tag s m => MonadState tag s (Trans.ContT r m) where
111+ get t = lift (get t)
112+ put t = lift . put t
113+ state t = lift . state t
114+
115+instance MonadState tag s m => MonadState tag s (Trans.ExceptT e m) where
116+ get t = lift (get t)
117+ put t = lift . put t
118+ state t = lift . state t
119+
120+instance MonadState tag s m => MonadState tag s (Trans.IdentityT m) where
121+ get t = lift (get t)
122+ put t = lift . put t
123+ state t = lift . state t
124+
125+instance MonadState tag s m => MonadState tag s (Trans.ListT m) where
126+ get t = lift (get t)
127+ put t = lift . put t
128+ state t = lift . state t
129+
130+instance MonadState tag s m => MonadState tag s (Trans.MaybeT m) where
131+ get t = lift (get t)
132+ put t = lift . put t
133+ state t = lift . state t
134+
135+instance MonadState tag s m => MonadState tag s (Trans.ReaderT r m) where
136+ get t = lift (get t)
137+ put t = lift . put t
138+ state t = lift . state t
139+
140+instance MonadState tag s m => MonadState tag s (Trans.Lazy.StateT s' m) where
141+ get t = lift (get t)
142+ put t = lift . put t
143+ state t = lift . state t
144+
145+instance MonadState tag s m => MonadState tag s (Trans.Strict.StateT s' m) where
146+ get t = lift (get t)
147+ put t = lift . put t
148+ state t = lift . state t
149+
150+instance (Monoid w, MonadState tag s m) => MonadState tag s (Trans.Lazy.WriterT w m) where
151+ get t = lift (get t)
152+ put t = lift . put t
153+ state t = lift . state t
154+
155+instance (Monoid w, MonadState tag s m) => MonadState tag s (Trans.Strict.WriterT w m) where
156+ get t = lift (get t)
157+ put t = lift . put t
158+ state t = lift . state t
src/Control/Monad/Ether/Writer.hsnew file+156
@@ -0,0 +1,156 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE UndecidableInstances #-}
6+{-# LANGUAGE DataKinds #-}
7+{-# LANGUAGE ConstraintKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE FunctionalDependencies #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE RankNTypes #-}
12+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
13+module Control.Monad.Ether.Writer
14+ (
15+ -- * MonadWriter class
16+ MonadWriter(..)
17+ , listens
18+ , censor
19+ -- * The Writer monad
20+ , Writer
21+ , runWriter
22+ , execWriter
23+ -- * The WriterT monad transformer
24+ , WriterT
25+ , writerT
26+ , runWriterT
27+ , execWriterT
28+ , mapWriterT
29+ ) where
30+
31+import Data.Proxy (Proxy(Proxy))
32+import Control.Monad.Trans (lift)
33+
34+import Control.Monad.Trans.Ether.Writer hiding (writer, tell, listen, pass)
35+import qualified Control.Monad.Trans.Ether.Reader as R
36+import qualified Control.Monad.Trans.Ether.State as S
37+import qualified Control.Monad.Trans.Ether.Except as E
38+import qualified Control.Monad.Trans.Ether.Writer as W
39+import qualified Control.Ether.Util as Util
40+
41+-- for mtl instances
42+import qualified Control.Monad.Trans.Except as Trans.E
43+import qualified Control.Monad.Trans.Identity as Trans.I
44+import qualified Control.Monad.Trans.Maybe as Trans.M
45+import qualified Control.Monad.Trans.Reader as Trans.R
46+import qualified Control.Monad.Trans.State.Lazy as Trans.S.Lazy
47+import qualified Control.Monad.Trans.State.Strict as Trans.S.Strict
48+import qualified Control.Monad.Trans.Writer.Lazy as Trans.W.Lazy
49+
50+class (Monoid w, Monad m) => MonadWriter tag w m | m tag -> w where
51+
52+ {-# MINIMAL (writer | tell), listen, pass #-}
53+
54+ -- | Embed a simple writer action.
55+ writer :: proxy tag -> (a, w) -> m a
56+ writer t ~(a, w) = do
57+ tell t w
58+ return a
59+
60+ -- | Append a value to the accumulator within the monad.
61+ tell :: proxy tag -> w -> m ()
62+ tell t w = writer t ((),w)
63+
64+ -- | Execute an action and add its accumulator
65+ -- to the value of the computation.
66+ listen :: proxy tag -> m a -> m (a, w)
67+
68+ -- | Execute an action which returns a value and a function,
69+ -- and return the value, applying the function to the accumulator.
70+ pass :: proxy tag -> m (a, w -> w) -> m a
71+
72+listens :: MonadWriter tag w m => proxy tag -> (w -> b) -> m a -> m (a, b)
73+listens t f m = do
74+ ~(a, w) <- listen t m
75+ return (a, f w)
76+
77+censor :: MonadWriter tag w m => proxy tag -> (w -> w) -> m a -> m a
78+censor t f m = pass t $ do
79+ a <- m
80+ return (a, f)
81+
82+instance {-# OVERLAPPING #-} (Monoid w, Monad m) => MonadWriter tag w (WriterT tag w m) where
83+ writer = W.writer
84+ tell = W.tell
85+ listen = W.listen
86+ pass = W.pass
87+
88+instance (Monoid w', MonadWriter tag w m) => MonadWriter tag w (WriterT tag' w' m) where
89+ writer t = lift . writer t
90+ tell t = lift . tell t
91+ listen t = W.liftListen Proxy (listen t)
92+ pass t = W.liftPass Proxy (pass t)
93+
94+-- Instances for other tagged transformers
95+
96+instance (MonadWriter tag w m) => MonadWriter tag w (R.ReaderT tag' r m) where
97+ writer t = lift . writer t
98+ tell t = lift . tell t
99+ listen t = R.mapReaderT Proxy (listen t)
100+ pass t = R.mapReaderT Proxy (pass t)
101+
102+instance (MonadWriter tag w m) => MonadWriter tag w (E.ExceptT tag' e m) where
103+ writer t = lift . writer t
104+ tell t = lift . tell t
105+ listen t = E.liftListen Proxy (listen t)
106+ pass t = E.liftPass Proxy (pass t)
107+
108+instance (MonadWriter tag w m) => MonadWriter tag w (S.StateT tag' e m) where
109+ writer t = lift . writer t
110+ tell t = lift . tell t
111+ listen t = S.liftListen Proxy (listen t)
112+ pass t = S.liftPass Proxy (pass t)
113+
114+-- Instances for mtl transformers
115+
116+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.E.ExceptT e m) where
117+ writer t = lift . writer t
118+ tell t = lift . tell t
119+ listen t = Trans.E.liftListen (listen t)
120+ pass t = Trans.E.liftPass (pass t)
121+
122+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.I.IdentityT m) where
123+ writer t = lift . writer t
124+ tell t = lift . tell t
125+ listen t = Trans.I.mapIdentityT (listen t)
126+ pass t = Trans.I.mapIdentityT (pass t)
127+
128+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.M.MaybeT m) where
129+ writer t = lift . writer t
130+ tell t = lift . tell t
131+ listen t = Trans.M.liftListen (listen t)
132+ pass t = Trans.M.liftPass (pass t)
133+
134+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.R.ReaderT r m) where
135+ writer t = lift . writer t
136+ tell t = lift . tell t
137+ listen t = Trans.R.mapReaderT (listen t)
138+ pass t = Trans.R.mapReaderT (pass t)
139+
140+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.S.Lazy.StateT s m) where
141+ writer t = lift . writer t
142+ tell t = lift . tell t
143+ listen t = Trans.S.Lazy.liftListen (listen t)
144+ pass t = Trans.S.Lazy.liftPass (pass t)
145+
146+instance (MonadWriter tag w m) => MonadWriter tag w (Trans.S.Strict.StateT s m) where
147+ writer t = lift . writer t
148+ tell t = lift . tell t
149+ listen t = Trans.S.Strict.liftListen (listen t)
150+ pass t = Trans.S.Strict.liftPass (pass t)
151+
152+instance (Monoid w', MonadWriter tag w m) => MonadWriter tag w (Trans.W.Lazy.WriterT w' m) where
153+ writer t = lift . writer t
154+ tell t = lift . tell t
155+ listen t = Util.liftListen_WriterT (listen t)
156+ pass t = Util.liftPass_WriterT (pass t)
src/Control/Monad/Trans/Ether/Except.hsnew file+151
@@ -0,0 +1,151 @@
1+{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE MultiParamTypeClasses #-}
3+{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE FlexibleContexts #-}
6+{-# LANGUAGE UndecidableInstances #-}
7+{-# LANGUAGE DataKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10+module Control.Monad.Trans.Ether.Except
11+ (
12+ -- * The Except monad
13+ Except
14+ , except
15+ , runExcept
16+ -- * The ExceptT monad transformer
17+ , ExceptT
18+ , exceptT
19+ , runExceptT
20+ , mapExceptT
21+ -- * Exception operations
22+ , throw
23+ , catch
24+ -- * Lifting other operations
25+ , liftCallCC
26+ , liftListen
27+ , liftPass
28+ , liftCatch
29+ ) where
30+
31+import Data.Proxy (Proxy(Proxy))
32+import Data.Functor.Identity (Identity(..))
33+import Data.Coerce (coerce)
34+import Control.Applicative (Alternative)
35+import Control.Monad (MonadPlus)
36+import Control.Monad.Fix (MonadFix)
37+import Control.Monad.Trans.Class (MonadTrans, lift)
38+import Control.Monad.IO.Class (MonadIO)
39+import Control.Ether.Tags (Taggable(..), Tagged(..))
40+import qualified Control.Ether.Util as Util
41+import GHC.Generics (Generic)
42+import qualified Control.Newtype as NT
43+
44+import qualified Control.Monad.Signatures as Sig
45+import qualified Control.Monad.Trans.Except as Trans
46+
47+import qualified Control.Monad.Cont.Class as Class
48+import qualified Control.Monad.Reader.Class as Class
49+import qualified Control.Monad.State.Class as Class
50+import qualified Control.Monad.Writer.Class as Class
51+import qualified Control.Monad.Error.Class as Class
52+
53+
54+-- | The parameterizable exception monad.
55+--
56+-- Computations are either exceptions or normal values.
57+--
58+-- The 'return' function returns a normal value, while '>>=' exits on
59+-- the first exception.
60+type Except tag e = ExceptT tag e Identity
61+
62+-- | Runs an 'Except' and returns either an exception or a normal value.
63+runExcept :: proxy tag -> Except tag e a -> Either e a
64+runExcept t = Trans.runExcept . untagged t
65+
66+-- | The exception monad transformer.
67+--
68+-- The 'return' function returns a normal value, while '>>=' exits on
69+-- the first exception.
70+
71+newtype ExceptT tag e m a = ExceptT (Trans.ExceptT e m a)
72+ deriving ( Generic
73+ , Functor, Applicative, Alternative, Monad, MonadPlus
74+ , MonadFix, MonadTrans, MonadIO )
75+
76+instance NT.Newtype (ExceptT tag e m a)
77+
78+instance Taggable (ExceptT tag e m) where
79+ type Tag (ExceptT tag e m) = 'Just tag
80+ type Inner (ExceptT tag e m) = 'Just m
81+
82+instance Tagged (ExceptT tag e m) tag where
83+ type Untagged (ExceptT tag e m) = Trans.ExceptT e m
84+
85+-- | Constructor for computations in the exception monad transformer.
86+exceptT :: proxy tag -> m (Either e a) -> ExceptT tag e m a
87+exceptT t = tagged t . Trans.ExceptT
88+
89+-- | Constructor for computations in the exception monad
90+-- (the inverse of 'runExcept').
91+except :: Monad m => proxy tag -> Either e a -> ExceptT tag e m a
92+except t = exceptT t . return
93+
94+-- | Runs an 'ExceptT' and returns either an exception or a normal value.
95+runExceptT :: proxy tag -> ExceptT tag e m a -> m (Either e a)
96+runExceptT t = Trans.runExceptT . untagged t
97+
98+-- | Transforms the computation inside an 'ExceptT'.
99+--
100+-- * @'runExceptT' tag ('mapExceptT' tag f m) = f ('runExceptT' tag m)@
101+mapExceptT
102+ :: proxy tag
103+ -> (m (Either e a) -> n (Either e' b))
104+ -> ExceptT tag e m a
105+ -> ExceptT tag e' n b
106+mapExceptT t f m = tagged t $ Trans.mapExceptT f (coerce m)
107+
108+throw :: Monad m => proxy tag -> e -> ExceptT tag e m a
109+throw t = tagged t . Trans.throwE
110+
111+catch :: Monad m => proxy tag -> ExceptT tag e m a -> (e -> ExceptT tag e m a) -> ExceptT tag e m a
112+catch t m h = tagged t $ Trans.catchE (coerce m) (coerce . h)
113+
114+-- | Lift a @callCC@ operation to the new monad.
115+liftCallCC :: proxy tag -> Sig.CallCC m (Either e a) (Either e b) -> Sig.CallCC (ExceptT tag e m) a b
116+liftCallCC t callCC f = tagged t $ Trans.liftCallCC callCC (coerce f)
117+
118+-- | Lift a @listen@ operation to the new monad.
119+liftListen :: Monad m => proxy tag -> Sig.Listen w m (Either e a) -> Sig.Listen w (ExceptT tag e m) a
120+liftListen t listen m = tagged t $ Trans.liftListen listen (coerce m)
121+
122+-- | Lift a @pass@ operation to the new monad.
123+liftPass :: Monad m => proxy tag -> Sig.Pass w m (Either e a) -> Sig.Pass w (ExceptT tag e m) a
124+liftPass t pass m = tagged t $ Trans.liftPass pass (coerce m)
125+
126+-- | Lift a @catchE@ operation to the new monad.
127+liftCatch :: proxy tag -> Sig.Catch e m (Either e' a) -> Sig.Catch e (ExceptT tag e' m) a
128+liftCatch t catchE m h = tagged t $ Util.liftCatch_ExceptT catchE (coerce m) (coerce h)
129+
130+instance Class.MonadCont m => Class.MonadCont (ExceptT tag e m) where
131+ callCC = liftCallCC Proxy Class.callCC
132+
133+instance Class.MonadReader r m => Class.MonadReader r (ExceptT tag e m) where
134+ ask = lift Class.ask
135+ local = mapExceptT Proxy . Class.local
136+ reader = lift . Class.reader
137+
138+instance Class.MonadState s m => Class.MonadState s (ExceptT tag e m) where
139+ get = lift Class.get
140+ put = lift . Class.put
141+ state = lift . Class.state
142+
143+instance Class.MonadWriter w m => Class.MonadWriter w (ExceptT tag e m) where
144+ writer = lift . Class.writer
145+ tell = lift . Class.tell
146+ listen = liftListen Proxy Class.listen
147+ pass = liftPass Proxy Class.pass
148+
149+instance Class.MonadError e' m => Class.MonadError e' (ExceptT tag e m) where
150+ throwError = lift . Class.throwError
151+ catchError = liftCatch Proxy Class.catchError
src/Control/Monad/Trans/Ether/Reader.hsnew file+164
@@ -0,0 +1,164 @@
1+{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE MultiParamTypeClasses #-}
3+{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE FlexibleContexts #-}
6+{-# LANGUAGE UndecidableInstances #-}
7+{-# LANGUAGE DataKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10+module Control.Monad.Trans.Ether.Reader
11+ (
12+ -- * The Reader monad
13+ Reader
14+ , reader
15+ , runReader
16+ -- * The ReaderT monad transformer
17+ , ReaderT
18+ , readerT
19+ , runReaderT
20+ , mapReaderT
21+ , withReaderT
22+ -- * Reader operations
23+ , ask
24+ , local
25+ -- * Lifting other operations
26+ , liftCatch
27+ , liftCallCC
28+ ) where
29+
30+import Data.Proxy (Proxy(Proxy))
31+import Data.Functor.Identity (Identity(..))
32+import Data.Coerce (coerce)
33+import Control.Applicative (Alternative)
34+import Control.Monad (MonadPlus)
35+import Control.Monad.Fix (MonadFix)
36+import Control.Monad.Trans.Class (MonadTrans, lift)
37+import Control.Monad.IO.Class (MonadIO)
38+import Control.Ether.Tags (Taggable(..), Tagged(..))
39+import GHC.Generics (Generic)
40+import qualified Control.Newtype as NT
41+
42+import qualified Control.Monad.Signatures as Sig
43+import qualified Control.Monad.Trans.Reader as Trans
44+
45+import qualified Control.Monad.Cont.Class as Class
46+import qualified Control.Monad.Reader.Class as Class
47+import qualified Control.Monad.State.Class as Class
48+import qualified Control.Monad.Writer.Class as Class
49+import qualified Control.Monad.Error.Class as Class
50+
51+-- | The parameterizable reader monad.
52+--
53+-- Computations are functions of a shared environment.
54+--
55+-- The 'return' function ignores the environment, while '>>=' passes
56+-- the inherited environment to both subcomputations.
57+type Reader tag r = ReaderT tag r Identity
58+
59+-- | The reader monad transformer,
60+-- which adds a read-only environment to the given monad.
61+--
62+-- The 'return' function ignores the environment, while '>>=' passes
63+-- the inherited environment to both subcomputations.
64+newtype ReaderT tag r m a = ReaderT (Trans.ReaderT r m a)
65+ deriving ( Generic
66+ , Functor, Applicative, Alternative, Monad, MonadPlus
67+ , MonadFix, MonadTrans, MonadIO )
68+
69+instance NT.Newtype (ReaderT tag r m a)
70+
71+instance Taggable (ReaderT tag r m) where
72+ type Tag (ReaderT tag r m) = 'Just tag
73+ type Inner (ReaderT tag r m) = 'Just m
74+
75+instance Tagged (ReaderT tag r m) tag where
76+ type Untagged (ReaderT tag r m) = Trans.ReaderT r m
77+
78+-- | Constructor for computations in the reader monad transformer.
79+readerT :: proxy tag -> (r -> m a) -> ReaderT tag r m a
80+readerT t = tagged t . Trans.ReaderT
81+
82+-- | Constructor for computations in the reader monad
83+-- (the inverse of 'runReader').
84+reader :: Monad m => proxy tag -> (r -> a) -> ReaderT tag r m a
85+reader t = tagged t . Trans.reader
86+
87+-- | Runs a 'ReaderT' with the given environment
88+-- and returns the vinal value.
89+runReaderT :: proxy tag -> ReaderT tag r m a -> r -> m a
90+runReaderT t = Trans.runReaderT . untagged t
91+
92+-- | Runs a 'ReaderT' with the given environment
93+-- and returns the vinal value.
94+runReader :: proxy tag -> Reader tag r a -> r -> a
95+runReader t = Trans.runReader . untagged t
96+
97+-- | Transform the computation inside a 'ReaderT'.
98+--
99+-- * @'runReaderT' tag ('mapReaderT' tag f m) = f . 'runReaderT' tag m@
100+mapReaderT :: proxy tag -> (m a -> n b) -> ReaderT tag r m a -> ReaderT tag r n b
101+mapReaderT t f m = tagged t $ Trans.mapReaderT f (coerce m)
102+
103+-- | Execute a computation in a modified environment
104+-- (a more general version of 'local').
105+--
106+-- * @'runReaderT' tag ('withReaderT' tag f m) = 'runReaderT' tag m . f@
107+withReaderT
108+ :: proxy tag
109+ -> (r' -> r)
110+ -- ^ The function to modify the environment.
111+ -> ReaderT tag r m a
112+ -- ^ Computation to run in the modified environment.
113+ -> ReaderT tag r' m a
114+withReaderT t f m = tagged t $ Trans.withReaderT f (coerce m)
115+
116+-- | Lift a @catchE@ operation to the new monad.
117+liftCatch :: proxy tag -> Sig.Catch e m a -> Sig.Catch e (ReaderT tag r m) a
118+liftCatch t f m h = tagged t $ Trans.liftCatch f (coerce m) (coerce h)
119+
120+-- | Lift a @callCC@ operation to the new monad.
121+liftCallCC :: proxy tag -> Sig.CallCC m a b -> Sig.CallCC (ReaderT tag r m) a b
122+liftCallCC t callCC f = tagged t $ Trans.liftCallCC callCC (coerce f)
123+
124+-- | Fetch the value of the environment.
125+ask :: Monad m => proxy tag -> ReaderT tag r m r
126+ask t = tagged t Trans.ask
127+
128+-- | Execute a computation in a modified environment
129+-- (a specialization of 'withReaderT').
130+--
131+-- * @'runReaderT' tag ('local' tag f m) = 'runReaderT' tag m . f@
132+local
133+ :: proxy tag
134+ -> (r -> r)
135+ -- ^ The function to modify the environment.
136+ -> ReaderT tag r m a
137+ -- ^ Computation to run in the modified environment.
138+ -> ReaderT tag r m a
139+local = withReaderT
140+
141+-- Instances for mtl classes
142+
143+instance Class.MonadCont m => Class.MonadCont (ReaderT tag r m) where
144+ callCC = liftCallCC Proxy Class.callCC
145+
146+instance Class.MonadReader r' m => Class.MonadReader r' (ReaderT tag r m) where
147+ ask = lift Class.ask
148+ local = mapReaderT Proxy . Class.local
149+ reader = lift . Class.reader
150+
151+instance Class.MonadState s m => Class.MonadState s (ReaderT tag r m) where
152+ get = lift Class.get
153+ put = lift . Class.put
154+ state = lift . Class.state
155+
156+instance Class.MonadWriter w m => Class.MonadWriter w (ReaderT tag r m) where
157+ writer = lift . Class.writer
158+ tell = lift . Class.tell
159+ listen = mapReaderT Proxy Class.listen
160+ pass = mapReaderT Proxy Class.pass
161+
162+instance Class.MonadError e m => Class.MonadError e (ReaderT tag r m) where
163+ throwError = lift . Class.throwError
164+ catchError = liftCatch Proxy Class.catchError
src/Control/Monad/Trans/Ether/State.hsnew file+177
@@ -0,0 +1,177 @@
1+{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE MultiParamTypeClasses #-}
3+{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE FlexibleContexts #-}
6+{-# LANGUAGE UndecidableInstances #-}
7+{-# LANGUAGE DataKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10+module Control.Monad.Trans.Ether.State
11+ (
12+ -- * The State monad
13+ State
14+ , state
15+ , runState
16+ , evalState
17+ , execState
18+ -- * The StateT monad transformer
19+ , StateT
20+ , stateT
21+ , runStateT
22+ , evalStateT
23+ , execStateT
24+ , mapStateT
25+ -- * State operations
26+ , get
27+ , put
28+ -- * Litfing other operations
29+ , liftCatch
30+ , liftCallCC'
31+ , liftListen
32+ , liftPass
33+ ) where
34+
35+import Data.Proxy (Proxy(Proxy))
36+import Data.Functor.Identity (Identity(..))
37+import Data.Coerce (coerce)
38+import Control.Applicative (Alternative)
39+import Control.Monad (MonadPlus)
40+import Control.Monad.Fix (MonadFix)
41+import Control.Monad.Trans.Class (MonadTrans, lift)
42+import Control.Monad.IO.Class (MonadIO)
43+import Control.Ether.Tags (Taggable(..), Tagged(..))
44+import GHC.Generics (Generic)
45+import qualified Control.Newtype as NT
46+
47+import qualified Control.Monad.Signatures as Sig
48+import qualified Control.Monad.Trans.State.Lazy as Trans
49+
50+import qualified Control.Monad.Cont.Class as Class
51+import qualified Control.Monad.Reader.Class as Class
52+import qualified Control.Monad.State.Class as Class
53+import qualified Control.Monad.Writer.Class as Class
54+import qualified Control.Monad.Error.Class as Class
55+
56+
57+-- | The parametrizable state monad.
58+--
59+-- Computations have access to a mutable state.
60+--
61+-- The 'return' function leaves the state unchanged, while '>>=' uses
62+-- the final state of the first computation as the initial state of the second.
63+type State tag r = StateT tag r Identity
64+
65+-- | The state monad transformer.
66+--
67+-- The 'return' function leaves the state unchanged, while '>>=' uses
68+-- the final state of the first computation as the initial state of the second.
69+newtype StateT tag s m a = StateT (Trans.StateT s m a)
70+ deriving ( Generic
71+ , Functor, Applicative, Alternative, Monad, MonadPlus
72+ , MonadFix, MonadTrans, MonadIO )
73+
74+instance NT.Newtype (StateT tag s m a)
75+
76+instance Taggable (StateT tag s m) where
77+ type Tag (StateT tag s m) = 'Just tag
78+ type Inner (StateT tag s m) = 'Just m
79+
80+instance Tagged (StateT tag s m) tag where
81+ type Untagged (StateT tag s m) = Trans.StateT s m
82+
83+-- | Constructor for computations in the state monad transformer.
84+stateT :: proxy tag -> (s -> m (a, s)) -> StateT tag s m a
85+stateT t = tagged t . Trans.StateT
86+
87+-- | Constructor for computations in the state monad
88+-- (the inverse of 'runState').
89+state :: Monad m => proxy tag -> (s -> (a, s)) -> StateT tag s m a
90+state t = tagged t . Trans.state
91+
92+-- | Runs a 'StateT' with the given initial state
93+-- and returns both the final value and the final state.
94+runStateT :: proxy tag -> StateT tag s m a -> s -> m (a, s)
95+runStateT t = Trans.runStateT . untagged t
96+
97+-- | Runs a 'StateT' with the given initial state
98+-- and returns the final value, discarding the final state.
99+evalStateT :: Monad m => proxy tag -> StateT tag s m a -> s -> m a
100+evalStateT t = Trans.evalStateT . untagged t
101+
102+-- | Runs a 'StateT' with the given initial state
103+-- and returns the final state, discarding the final value.
104+execStateT :: Monad m => proxy tag -> StateT tag s m a -> s -> m s
105+execStateT t = Trans.execStateT . untagged t
106+
107+-- | Runs a 'State' with the given initial state
108+-- and returns both the final value and the final state.
109+runState :: proxy tag -> State tag s a -> s -> (a, s)
110+runState t = Trans.runState . untagged t
111+
112+-- | Runs a 'State' with the given initial state
113+-- and returns the final value, discarding the final state.
114+evalState :: proxy tag -> State tag s a -> s -> a
115+evalState t = Trans.evalState . untagged t
116+
117+-- | Runs a 'State' with the given initial state
118+-- and returns the final state, discarding the final value.
119+execState :: proxy tag -> State tag s a -> s -> s
120+execState t = Trans.execState . untagged t
121+
122+-- | Transform the computation inside a 'StateT'.
123+--
124+-- * @'runStateT' tag ('mapStateT' tag f m) = f . 'runStateT' tag m@
125+mapStateT :: proxy tag -> (m (a, s) -> n (b, s)) -> StateT tag s m a -> StateT tag s n b
126+mapStateT t f m = tagged t $ Trans.mapStateT f (coerce m)
127+
128+-- | Fetch the current value of the state within the monad.
129+get :: Monad m => proxy tag -> StateT tag s m s
130+get t = tagged t Trans.get
131+
132+-- | Set the value of the state within the monad.
133+put :: Monad m => proxy tag -> s -> StateT tag s m ()
134+put t = tagged t . Trans.put
135+
136+-- | Lift a @catchE@ operation to the new monad.
137+liftCatch :: proxy tag -> Sig.Catch e m (a, s) -> Sig.Catch e (StateT tag s m) a
138+liftCatch t f m h = tagged t $ Trans.liftCatch f (coerce m) (coerce h)
139+
140+-- | Lift a @listen@ operation to the new monad.
141+liftListen :: Monad m => proxy tag -> Sig.Listen w m (a, s) -> Sig.Listen w (StateT tag s m) a
142+liftListen t listen m = tagged t $ Trans.liftListen listen (coerce m)
143+
144+-- | In-situ lifting of a @callCC@ operation to the new monad.
145+-- This version uses the current state on entering the continuation.
146+-- It does not satisfy the uniformity property (see "Control.Monad.Signatures").
147+liftCallCC' :: proxy tag -> Sig.CallCC m (a, s) (b, s) -> Sig.CallCC (StateT tag s m) a b
148+liftCallCC' t callCC f = tagged t $ Trans.liftCallCC' callCC (coerce f)
149+
150+-- | Lift a @pass@ operation to the new monad.
151+liftPass :: Monad m => proxy tag -> Sig.Pass w m (a,s) -> Sig.Pass w (StateT tag s m) a
152+liftPass t pass m = tagged t $ Trans.liftPass pass (coerce m)
153+
154+-- Instances for mtl classes
155+
156+instance Class.MonadCont m => Class.MonadCont (StateT tag s m) where
157+ callCC = liftCallCC' Proxy Class.callCC
158+
159+instance Class.MonadReader r m => Class.MonadReader r (StateT tag s m) where
160+ ask = lift Class.ask
161+ local = mapStateT Proxy . Class.local
162+ reader = lift . Class.reader
163+
164+instance Class.MonadState s' m => Class.MonadState s' (StateT tag s m) where
165+ get = lift Class.get
166+ put = lift . Class.put
167+ state = lift . Class.state
168+
169+instance Class.MonadWriter w m => Class.MonadWriter w (StateT tag s m) where
170+ writer = lift . Class.writer
171+ tell = lift . Class.tell
172+ listen = liftListen Proxy Class.listen
173+ pass = liftPass Proxy Class.pass
174+
175+instance Class.MonadError e m => Class.MonadError e (StateT tag s m) where
176+ throwError = lift . Class.throwError
177+ catchError = liftCatch Proxy Class.catchError
src/Control/Monad/Trans/Ether/Writer.hsnew file+164
@@ -0,0 +1,164 @@
1+{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE MultiParamTypeClasses #-}
3+{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE FlexibleContexts #-}
6+{-# LANGUAGE UndecidableInstances #-}
7+{-# LANGUAGE DataKinds #-}
8+{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10+module Control.Monad.Trans.Ether.Writer
11+ (
12+ -- * The Writer monad
13+ Writer
14+ , writer
15+ , runWriter
16+ , execWriter
17+ -- * The WriterT monad transformer
18+ , WriterT
19+ , writerT
20+ , runWriterT
21+ , execWriterT
22+ , mapWriterT
23+ -- * Writer operations
24+ , tell
25+ , listen
26+ , pass
27+ -- * Lifting other operations
28+ , liftCallCC
29+ , liftCatch
30+ , liftListen
31+ , liftPass
32+ ) where
33+
34+import Data.Proxy (Proxy(Proxy))
35+import Data.Functor.Identity (Identity(..))
36+import Data.Coerce (coerce)
37+import Control.Applicative (Alternative)
38+import Control.Monad (MonadPlus)
39+import Control.Monad.Fix (MonadFix)
40+import Control.Monad.Trans.Class (MonadTrans, lift)
41+import Control.Monad.IO.Class (MonadIO)
42+import Control.Ether.Tags (Taggable(..), Tagged(..))
43+import qualified Control.Ether.Util as Util
44+import GHC.Generics (Generic)
45+import qualified Control.Newtype as NT
46+
47+import qualified Control.Monad.Signatures as Sig
48+import qualified Control.Monad.Trans.Writer.Lazy as Trans
49+
50+import qualified Control.Monad.Cont.Class as Class
51+import qualified Control.Monad.Reader.Class as Class
52+import qualified Control.Monad.State.Class as Class
53+import qualified Control.Monad.Writer.Class as Class
54+import qualified Control.Monad.Error.Class as Class
55+
56+-- | The parametrizable writer monad.
57+--
58+-- Computations can accumulate a monoid value.
59+--
60+-- The 'return' function produces the output 'mempty', while '>>=' combines
61+-- the outputs of the subcomputations using 'mappend'.
62+type Writer tag w = WriterT tag w Identity
63+
64+-- | The writer monad transformer.
65+--
66+-- The 'return' function produces the output 'mempty', while '>>=' combines
67+-- the outputs of the subcomputations using 'mappend'.
68+newtype WriterT tag w m a = WriterT (Trans.WriterT w m a)
69+ deriving ( Generic
70+ , Functor, Applicative, Alternative, Monad, MonadPlus
71+ , MonadFix, MonadTrans, MonadIO )
72+
73+instance NT.Newtype (WriterT tag w m a)
74+
75+instance Taggable (WriterT tag w m) where
76+ type Tag (WriterT tag w m) = 'Just tag
77+ type Inner (WriterT tag w m) = 'Just m
78+
79+instance Tagged (WriterT tag w m) tag where
80+ type Untagged (WriterT tag w m) = Trans.WriterT w m
81+
82+-- | Constructor for computations in the writer monad transformer.
83+writerT :: proxy tag -> m (a, w) -> WriterT tag w m a
84+writerT t = tagged t . Trans.WriterT
85+
86+-- | Constructor for computations in the writer monad
87+-- (the inverse of 'runWriter').
88+writer :: Monad m => proxy tag -> (a, w) -> WriterT tag w m a
89+writer t = tagged t . Trans.writer
90+
91+-- | Runs a 'WriterT' and returns both the normal value
92+-- and the final accumulator.
93+runWriterT :: proxy tag -> WriterT tag w m a -> m (a, w)
94+runWriterT t = Trans.runWriterT . untagged t
95+
96+-- | Runs a 'Writer' and returns both the normal value
97+-- and the final accumulator.
98+runWriter :: proxy tag -> Writer tag w a -> (a, w)
99+runWriter t = Trans.runWriter . untagged t
100+
101+-- | Runs a 'WriterT' and returns the final accumulator,
102+-- discarding the normal value.
103+execWriterT :: Monad m => proxy tag -> WriterT tag w m a -> m w
104+execWriterT t = Trans.execWriterT . untagged t
105+
106+-- | Runs a 'Writer' and returns the final accumulator,
107+-- discarding the normal value.
108+execWriter :: proxy tag -> Writer tag w a -> w
109+execWriter t = Trans.execWriter . untagged t
110+
111+-- | Transform the computation inside a 'WriterT'.
112+--
113+-- * @'runWriterT' tag ('mapWriterT' tag f m) = f ('runWriterT' tag m)@
114+mapWriterT :: proxy tag -> (m (a, w) -> n (b, w')) -> WriterT tag w m a -> WriterT tag w' n b
115+mapWriterT t f m = tagged t $ Trans.mapWriterT f (coerce m)
116+
117+-- | Appends a value to the accumulator within the monad.
118+tell :: Monad m => proxy tag -> w -> WriterT tag w m ()
119+tell t w = writer t ((), w)
120+
121+listen :: (Monoid w, Monad m) => proxy tag -> WriterT tag w m a -> WriterT tag w m (a, w)
122+listen t m = tagged t $ Trans.listen (coerce m)
123+
124+pass :: (Monoid w, Monad m) => proxy tag -> WriterT tag w m (a, w -> w) -> WriterT tag w m a
125+pass t m = tagged t $ Trans.pass (coerce m)
126+
127+-- | Lift a @catchE@ operation to the new monad.
128+liftCatch :: proxy tag -> Sig.Catch e m (a, w) -> Sig.Catch e (WriterT tag w m) a
129+liftCatch t f m h = tagged t $ Trans.liftCatch f (coerce m) (coerce h)
130+
131+-- | Lift a @callCC@ operation to the new monad.
132+liftCallCC :: Monoid w => proxy tag -> Sig.CallCC m (a, w) (b, w) -> Sig.CallCC (WriterT tag w m) a b
133+liftCallCC t callCC f = tagged t $ Trans.liftCallCC callCC (coerce f)
134+
135+-- | Lift a @listen@ operation to the new monad.
136+liftListen :: Monad m => proxy tag -> Sig.Listen w' m (a, w) -> Sig.Listen w' (WriterT tag w m) a
137+liftListen t listen m = tagged t $ Util.liftListen_WriterT listen (coerce m)
138+
139+-- | Lift a @pass@ operation to the new monad.
140+liftPass :: Monad m => proxy tag -> Sig.Pass w' m (a, w) -> Sig.Pass w' (WriterT tag w m) a
141+liftPass t pass m = tagged t $ Util.liftPass_WriterT pass (coerce m)
142+
143+instance (Monoid w, Class.MonadCont m) => Class.MonadCont (WriterT tag w m) where
144+ callCC = liftCallCC Proxy Class.callCC
145+
146+instance (Monoid w, Class.MonadReader r m) => Class.MonadReader r (WriterT tag w m) where
147+ ask = lift Class.ask
148+ local = mapWriterT Proxy . Class.local
149+ reader = lift . Class.reader
150+
151+instance (Monoid w, Class.MonadState s m) => Class.MonadState s (WriterT tag w m) where
152+ get = lift Class.get
153+ put = lift . Class.put
154+ state = lift . Class.state
155+
156+instance (Monoid w, Class.MonadWriter w' m) => Class.MonadWriter w' (WriterT tag w m) where
157+ writer = lift . Class.writer
158+ tell = lift . Class.tell
159+ listen = liftListen Proxy Class.listen
160+ pass = liftPass Proxy Class.pass
161+
162+instance (Monoid w, Class.MonadError e m) => Class.MonadError e (WriterT tag w m) where
163+ throwError = lift . Class.throwError
164+ catchError = liftCatch Proxy Class.catchError
src/Ether.hsdeleted−25
@@ -1,25 +0,0 @@
1−module Ether
2− ( module Control.Monad
3− , module Control.Monad.Fix
4− , module Control.Monad.Trans.Identity
5− , module Data.Functor.Identity
6− , module Data.Tagged
7− , module Ether.Reader
8− , module Ether.Writer
9− , module Ether.State
10− , module Ether.Except
11− , module Ether.TagDispatch
12− , module Ether.TaggedTrans
13− ) where
14−
15−import Control.Monad
16−import Control.Monad.Fix
17−import Control.Monad.Trans.Identity
18−import Data.Functor.Identity
19−import Data.Tagged
20−import Ether.Reader
21−import Ether.Writer
22−import Ether.State
23−import Ether.Except
24−import Ether.TagDispatch
25−import Ether.TaggedTrans
src/Ether/Except.hsdeleted−127
@@ -1,127 +0,0 @@
1−module Ether.Except
2− (
3− -- * MonadExcept class
4− MonadExcept
5− , throw
6− , catch
7− -- * The Except monad
8− , Except
9− , runExcept
10− -- * The ExceptT monad transformer
11− , ExceptT
12− , exceptT
13− , runExceptT
14− -- * MonadExcept class (implicit)
15− , MonadExcept'
16− , throw'
17− , catch'
18− -- * The Except monad (implicit)
19− , Except'
20− , runExcept'
21− -- * The ExceptT monad transformer (implicit)
22− , ExceptT'
23− , exceptT'
24− , runExceptT'
25− -- * Internal labels
26− , TAGGED
27− , EXCEPT
28− ) where
29−
30−import qualified Control.Monad.Except as T
31−import Control.Monad.Signatures (Catch)
32−import qualified Control.Monad.Trans.Lift.Catch as Lift
33−import Data.Coerce
34−import Data.Functor.Identity
35−
36−import Ether.TaggedTrans
37−import Ether.Internal
38−
39−class Monad m => MonadExcept tag e m | m tag -> e where
40−
41− -- | Is used within a monadic computation to begin exception processing.
42− throw :: e -> m a
43−
44− -- | A TaggedTrans function to handle previous exceptions and return to
45− -- normal execution.
46− catch :: m a -> (e -> m a) -> m a
47−
48−instance {-# OVERLAPPABLE #-}
49− ( Lift.LiftCatch t
50− , Monad (t m)
51− , MonadExcept tag e m
52− ) => MonadExcept tag e (t m) where
53− throw = Lift.lift . throw @tag
54− catch = Lift.liftCatch (catch @tag)
55−
56−-- | Encode type-level information for 'ExceptT'.
57−data EXCEPT
58−
59−-- | The parameterizable exception monad.
60−--
61−-- Computations are either exceptions or normal values.
62−--
63−-- The 'return' function returns a normal value, while '>>=' exits on
64−-- the first exception.
65−type Except tag e = ExceptT tag e Identity
66−
67−-- | The exception monad transformer.
68−--
69−-- The 'return' function returns a normal value, while '>>=' exits on
70−-- the first exception.
71−type ExceptT tag e = TaggedTrans (TAGGED EXCEPT tag) (T.ExceptT e)
72−
73−-- | Runs an 'Except' and returns either an exception or a normal value.
74−runExcept :: forall tag e a . Except tag e a -> Either e a
75−runExcept = coerce (T.runExcept @e @a)
76−
77−-- | Runs an 'ExceptT' and returns either an exception or a normal value.
78−runExceptT :: forall tag e m a . ExceptT tag e m a -> m (Either e a)
79−runExceptT = coerce (T.runExceptT @e @m @a)
80−
81−-- | Constructor for computations in the exception monad transformer.
82−exceptT :: forall tag e m a . m (Either e a) -> ExceptT tag e m a
83−exceptT = coerce (T.ExceptT @e @m @a)
84−
85−type instance HandleSuper EXCEPT e trans = ()
86−type instance HandleConstraint EXCEPT e trans m =
87− T.MonadError e (trans m)
88−
89−instance Handle EXCEPT e (T.ExceptT e) where
90− handling r = r
91−
92−instance
93− ( Handle EXCEPT e trans
94− , Monad m, Monad (trans m)
95− ) => MonadExcept tag e (TaggedTrans (TAGGED EXCEPT tag) trans m)
96− where
97−
98− throw =
99− handling @EXCEPT @e @trans @m $
100− coerce (T.throwError @e @(trans m) @a) ::
101− forall eff a . e -> TaggedTrans eff trans m a
102−
103− catch =
104− handling @EXCEPT @e @trans @m $
105− coerce (T.catchError @e @(trans m) @a) ::
106− forall eff a . Catch e (TaggedTrans eff trans m) a
107−
108−type MonadExcept' e = MonadExcept e e
109−
110−throw' :: forall e m a . MonadExcept' e m => e -> m a
111−throw' = throw @e
112−
113−catch' :: forall e m a . MonadExcept' e m => m a -> (e -> m a) -> m a
114−catch' = catch @e
115−
116−type Except' e = Except e e
117−
118−runExcept' :: Except' e a -> Either e a
119−runExcept' = runExcept
120−
121−type ExceptT' e = ExceptT e e
122−
123−exceptT' :: m (Either e a) -> ExceptT' e m a
124−exceptT' = exceptT
125−
126−runExceptT' :: ExceptT' e m a -> m (Either e a)
127−runExceptT' = runExceptT
src/Ether/Internal.hsdeleted−68
@@ -1,68 +0,0 @@
1−module Ether.Internal
2− ( Tagged(..)
3− , TagsK
4− , Tags
5− , HasLens(..)
6− , LensLike
7− , Lens
8− , Lens'
9− , ReifiedLens(..)
10− , ReifiedLens'
11− , view
12− , over
13− , HList(..)
14− , KindOf
15− , TAGGED
16− , HandleSuper
17− , HandleConstraint
18− , Handle(..)
19− , makeTupleInstancesHasLens
20− ) where
21−
22−import Control.Applicative
23−import Data.Coerce
24−import Data.Functor.Identity
25−import Data.Kind
26−import Data.Tagged
27−import GHC.Exts (Constraint)
28−
29−import Ether.Internal.HasLens
30−import Ether.Internal.Tags
31−import Ether.Internal.TH_TupleInstances (makeTupleInstancesHasLens)
32−import Ether.Internal.TupleInstances ()
33−
34−data TAGGED e t
35−
36−type K_Monad = Type -> Type
37−
38−type K_Trans = K_Monad -> K_Monad
39−
40−type family
41− HandleSuper
42− (eff :: keff)
43− (p :: kp)
44− (trans :: K_Trans)
45− :: Constraint
46−
47−type family
48− HandleConstraint
49− (eff :: keff)
50− (p :: kp)
51− (trans :: K_Trans) (m :: K_Monad)
52− :: Constraint
53−
54−class
55− HandleSuper eff p trans =>
56− Handle eff p (trans :: K_Trans) | eff trans -> p
57− where
58− handling :: Monad m => (HandleConstraint eff p trans m => r) -> r
59−
60−newtype ReifiedLens s t a b = Lens (Lens s t a b)
61−
62−type ReifiedLens' s a = ReifiedLens s s a a
63−
64−view :: LensLike (Const a) s t a b -> s -> a
65−view l = coerce (l Const)
66−
67−over :: LensLike Identity s t a b -> (a -> b) -> s -> t
68−over = coerce
src/Ether/Internal/HasLens.hsdeleted−24
@@ -1,24 +0,0 @@
1−module Ether.Internal.HasLens
2− ( LensLike
3− , Lens
4− , Lens'
5− , HasLens(..)
6− ) where
7−
8−import Data.Tagged
9−import Data.Coerce
10−
11−type LensLike f s t a b = (a -> f b) -> s -> f t
12−
13−type Lens s t a b = forall f. Functor f => LensLike f s t a b
14−
15−type Lens' s a = Lens s s a a
16−
17−class HasLens tag outer inner | tag outer -> inner where
18− lensOf :: Lens' outer inner
19−
20−instance HasLens a a a where
21− lensOf = id
22−
23−instance HasLens t (Tagged t a) a where
24− lensOf = \f -> fmap coerce . f . coerce
src/Ether/Internal/TH_TupleInstances.hsdeleted−79
@@ -1,79 +0,0 @@
1−module Ether.Internal.TH_TupleInstances
2− ( makeTupleInstancesTagsK
3− , makeTupleInstancesTags
4− , makeTupleInstancesHasLens
5− ) where
6−
7−import Data.Tagged
8−import Data.Traversable
9−import Data.List as List
10−import qualified Language.Haskell.TH as TH
11−
12−import Ether.Internal.HasLens
13−import Ether.Internal.Tags
14−import Ether.Internal.TH_Utils
15−
16−makeTupleInstancesTagsK :: TH.DecsQ
17−makeTupleInstancesTagsK = do
18− for [2..tupCount] $ \n -> do
19− let
20− tupTy = List.foldl' TH.AppT (TH.ConT (TH.tupleTypeName n)) $
21− (\k -> TH.ConT ''Tagged `TH.AppT`
22− TH.VarT (tagName k) `TH.AppT`
23− TH.VarT (varName k)) <$> [0..n-1]
24− tagsList = List.foldr
25− (\a b -> TH.PromotedConsT `TH.AppT` a `TH.AppT` b)
26− TH.PromotedNilT
27− (TH.AppT (TH.ConT ''KindOf) . TH.VarT . tagName <$> [0..n-1])
28− return $
29− TH.TySynInstD ''TagsK (TH.TySynEqn [tupTy] tagsList)
30−
31−makeTupleInstancesTags :: TH.DecsQ
32−makeTupleInstancesTags = do
33− for [2..tupCount] $ \n -> do
34− let
35− tupTy = List.foldl' TH.AppT (TH.ConT (TH.tupleTypeName n)) $
36− (\k -> TH.ConT ''Tagged `TH.AppT`
37− TH.VarT (tagName k) `TH.AppT`
38− TH.VarT (varName k)) <$> [0..n-1]
39− tagsList = List.foldr
40− (\a b -> TH.PromotedT 'HCons `TH.AppT` a `TH.AppT` b)
41− (TH.PromotedT 'HNil)
42− (TH.VarT . tagName <$> [0..n-1])
43− return $
44− TH.TySynInstD ''Tags (TH.TySynEqn [tupTy] tagsList)
45−
46−makeTupleInstancesHasLens :: [Int] -> TH.DecsQ
47−makeTupleInstancesHasLens range = List.concat <$> do
48− for range $ \n ->
49− for [0..n-1] $ \k -> do
50− let
51− tag = TH.mkName "tag"
52− prev = varName <$> [0..k-1]
53− cur = varName k
54− next = varName <$> [k+1..n-1]
55− tupTy = foldl TH.AppT (TH.ConT (TH.tupleTypeName n))
56− ( map TH.VarT prev ++
57− [TH.ConT ''Tagged `TH.AppT` TH.VarT tag `TH.AppT` TH.VarT cur] ++
58− map TH.VarT next )
59− let
60− cur' = TH.mkName "x"
61− f = TH.mkName "f"
62− return $
63− TH.InstanceD Nothing []
64− (TH.ConT ''HasLens `TH.AppT` TH.VarT tag `TH.AppT` tupTy `TH.AppT` TH.VarT cur)
65− [ TH.FunD 'lensOf
66− [ TH.Clause
67− [TH.VarP f, TH.TupP
68− ( map TH.VarP prev ++
69− [TH.ConP 'Tagged [TH.VarP cur]] ++
70− map TH.VarP next )]
71− (TH.NormalB $
72− TH.VarE 'fmap `TH.AppE`
73− (TH.LamE [TH.VarP cur']
74− (TH.TupE
75− ( map TH.VarE prev ++
76− [TH.ConE 'Tagged `TH.AppE` TH.VarE cur'] ++
77− map TH.VarE next ))) `TH.AppE`
78− (TH.VarE f `TH.AppE` TH.VarE cur) )
79− [] ] ]
src/Ether/Internal/TH_Utils.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Ether.Internal.TH_Utils
2− ( tupCount
3− , varName
4− , tagName
5− ) where
6−
7−import qualified Language.Haskell.TH as TH
8−
9−tupCount :: Int
10−tupCount = 62
11−
12−varName, tagName :: Int -> TH.Name
13−varName k = TH.mkName ('a' : show k)
14−tagName k = TH.mkName ('t' : show k)
src/Ether/Internal/Tags.hsdeleted−18
@@ -1,18 +0,0 @@
1−module Ether.Internal.Tags
2− ( Tags
3− , TagsK
4− , HList(..)
5− , KindOf
6− ) where
7−
8−import Data.Kind
9−
10−data HList xs where
11− HNil :: HList '[]
12− HCons :: x -> HList xs -> HList (x ': xs)
13−
14−type KindOf (a :: k) = k
15−
16−type family TagsK (p :: Type) :: [Type]
17−type family Tags (p :: Type) :: HList (TagsK p)
18−
src/Ether/Internal/TupleInstances.hsdeleted−24
@@ -1,24 +0,0 @@
1−{-# OPTIONS -fno-warn-orphans #-}
2−{-# LANGUAGE CPP #-}
3−
4−module Ether.Internal.TupleInstances () where
5−
6−import Data.Tagged
7−import Ether.Internal.Tags
8−import Ether.Internal.TH_TupleInstances
9−
10−type instance TagsK () = '[]
11−type instance TagsK (Tagged t a) = '[KindOf t]
12−type instance TagsK (Tagged t0 a, Tagged t1 b) = '[KindOf t0, KindOf t1]
13−
14−makeTupleInstancesTagsK
15−
16−type instance Tags () = 'HNil
17−type instance Tags (Tagged t a) = 'HCons t 'HNil
18−type instance Tags (Tagged t0 a, Tagged t1 b) = 'HCons t0 ('HCons t1 'HNil)
19−
20−makeTupleInstancesTags
21−
22−#ifndef DISABLE_TUP_INSTANCES
23−makeTupleInstancesHasLens [2..62]
24−#endif
src/Ether/Reader.hsdeleted−236
@@ -1,236 +0,0 @@
1−module Ether.Reader
2− (
3− -- * MonadReader class
4− MonadReader
5− , ask
6− , local
7− , reader
8− , asks
9− -- * The Reader monad
10− , Reader
11− , runReader
12− -- * The ReaderT monad transformer
13− , ReaderT
14− , readerT
15− , runReaderT
16− -- * The Reader monad (flattened)
17− , Readers
18− , runReaders
19− -- * The ReaderT monad transformer (flattened)
20− , ReadersT
21− , runReadersT
22− -- * MonadReader class (implicit)
23− , MonadReader'
24− , local'
25− , ask'
26− , reader'
27− , asks'
28− -- * The Reader monad (implicit)
29− , Reader'
30− , runReader'
31− -- * The ReaderT monad transformer (implicit)
32− , ReaderT'
33− , readerT'
34− , runReaderT'
35− -- * Internal labels
36− , TAGGED
37− , READER
38− , READERS
39− ) where
40−
41−import qualified Control.Monad.Reader as T
42−import qualified Control.Monad.Trans.Lift.Local as Lift
43−import Control.Monad.Trans.Lift.Local (Local)
44−import Data.Coerce
45−import Data.Functor.Identity
46−import Data.Kind
47−
48−import Ether.TaggedTrans
49−import Ether.Internal
50−
51−class Monad m => MonadReader tag r m | m tag -> r where
52−
53− {-# MINIMAL (ask | reader), local #-}
54−
55− -- | Retrieves the monad environment.
56− ask :: m r
57− ask = reader @tag id
58−
59− -- | Executes a computation in a modified environment.
60− local
61− :: (r -> r)
62− -- ^ The function to modify the environment.
63− -> m a
64− -- ^ @Reader@ to run in the modified environment.
65− -> m a
66−
67− -- | Retrieves a function of the current environment.
68− reader
69− :: (r -> a)
70− -- ^ The selector function to apply to the environment.
71− -> m a
72− reader f = fmap f (ask @tag)
73−
74−instance {-# OVERLAPPABLE #-}
75− ( Lift.LiftLocal t
76− , Monad (t m)
77− , MonadReader tag r m
78− ) => MonadReader tag r (t m)
79− where
80− ask = Lift.lift (ask @tag)
81− local = Lift.liftLocal (ask @tag) (local @tag)
82− reader = Lift.lift . reader @tag
83−
84−instance {-# OVERLAPPABLE #-}
85− ( Monad (trans m)
86− , MonadReader tag r (TaggedTrans effs trans m)
87− ) => MonadReader tag r (TaggedTrans (eff ': effs) trans (m :: Type -> Type))
88− where
89−
90− ask =
91− (coerce ::
92− TaggedTrans effs trans m r ->
93− TaggedTrans (eff ': effs) trans m r)
94− (ask @tag)
95−
96− local =
97− (coerce :: forall a .
98− Lift.Local r (TaggedTrans effs trans m) a ->
99− Lift.Local r (TaggedTrans (eff ': effs) trans m) a)
100− (local @tag)
101−
102− reader =
103− (coerce :: forall a .
104− ((r -> a) -> TaggedTrans effs trans m a) ->
105− ((r -> a) -> TaggedTrans (eff ': effs) trans m a))
106− (reader @tag)
107−
108−-- | Retrieves a function of the current environment.
109−asks
110− :: forall tag r m a
111− . MonadReader tag r m
112− => (r -> a)
113− -- ^ The selector function to apply to the environment.
114− -> m a
115−asks = reader @tag
116−
117−-- | Encode type-level information for 'ReaderT'.
118−data READER
119−
120−-- | The parameterizable reader monad.
121−--
122−-- Computations are functions of a shared environment.
123−--
124−-- The 'return' function ignores the environment, while '>>=' passes
125−-- the inherited environment to both subcomputations.
126−type Reader tag r = ReaderT tag r Identity
127−
128−-- | The reader monad transformer,
129−-- which adds a read-only environment to the given monad.
130−--
131−-- The 'return' function ignores the environment, while '>>=' passes
132−-- the inherited environment to both subcomputations.
133−type ReaderT tag r = TaggedTrans (TAGGED READER tag) (T.ReaderT r)
134−
135−-- | Constructor for computations in the reader monad transformer.
136−readerT :: forall tag r m a . (r -> m a) -> ReaderT tag r m a
137−readerT = coerce (T.ReaderT @r @m @a)
138−
139−-- | Runs a 'ReaderT' with the given environment
140−-- and returns the final value.
141−runReaderT :: forall tag r m a . ReaderT tag r m a -> r -> m a
142−runReaderT = coerce (T.runReaderT @r @m @a)
143−
144−-- | Runs a 'ReaderT' with the given environment
145−-- and returns the final value.
146−runReader :: forall tag r a . Reader tag r a -> r -> a
147−runReader = coerce (T.runReader @r @a)
148−
149−type instance HandleSuper READER r trans = ()
150−type instance HandleConstraint READER r trans m =
151− T.MonadReader r (trans m)
152−
153−instance Handle READER r (T.ReaderT r) where
154− handling r = r
155−
156−instance
157− ( Handle READER r trans
158− , Monad m, Monad (trans m)
159− ) => MonadReader tag r (TaggedTrans (TAGGED READER tag) trans m)
160− where
161−
162− ask =
163− handling @READER @r @trans @m $
164− coerce (T.ask @r @(trans m))
165−
166− local =
167− handling @READER @r @trans @m $
168− coerce (T.local @r @(trans m) @a) ::
169− forall eff a . Local r (TaggedTrans eff trans m) a
170−
171− reader =
172− handling @READER @r @trans @m $
173− coerce (T.reader @r @(trans m) @a) ::
174− forall eff a . (r -> a) -> TaggedTrans eff trans m a
175−
176−instance
177− ( HasLens tag payload r
178− , Handle READER payload trans
179− , Monad m, Monad (trans m)
180− ) => MonadReader tag r (TaggedTrans (TAGGED READER tag ': effs) trans m)
181− where
182−
183− ask =
184− handling @READER @payload @trans @m $
185− (coerce :: forall eff a .
186− trans m a ->
187− TaggedTrans eff trans m a)
188− (T.asks (view (lensOf @tag @payload @r)))
189−
190− local f =
191− handling @READER @payload @trans @m $
192− (coerce :: forall eff a .
193− (trans m a -> trans m a) ->
194− (TaggedTrans eff trans m a -> TaggedTrans eff trans m a))
195− (T.local (over (lensOf @tag @payload @r) f))
196−
197−type family READERS (ts :: HList xs) :: [Type] where
198− READERS 'HNil = '[]
199− READERS ('HCons t ts) = TAGGED READER t ': READERS ts
200−
201−type ReadersT r = TaggedTrans (READERS (Tags r)) (T.ReaderT r)
202−
203−type Readers r = ReadersT r Identity
204−
205−runReadersT :: forall p m a . ReadersT p m a -> p -> m a
206−runReadersT = coerce (T.runReaderT @p @m @a)
207−
208−runReaders :: forall p a . Readers p a -> p -> a
209−runReaders = coerce (T.runReader @p @a)
210−
211−type ReaderT' r = ReaderT r r
212−
213−readerT' :: (r -> m a) -> ReaderT' r m a
214−readerT' = readerT
215−
216−runReaderT' :: ReaderT' r m a -> r -> m a
217−runReaderT' = runReaderT
218−
219−type Reader' r = Reader r r
220−
221−runReader' :: Reader' r a -> r -> a
222−runReader' = runReader
223−
224−type MonadReader' r = MonadReader r r
225−
226−local' :: forall r m a . MonadReader' r m => (r -> r) -> m a -> m a
227−local' = local @r
228−
229−ask' :: forall r m . MonadReader' r m => m r
230−ask' = ask @r
231−
232−reader' :: forall r m a . MonadReader' r m => (r -> a) -> m a
233−reader' = reader @r
234−
235−asks' :: forall r m a . MonadReader' r m => (r -> a) -> m a
236−asks' = asks @r
src/Ether/State.hsdeleted−415
@@ -1,415 +0,0 @@
1−module Ether.State
2− (
3− -- * MonadState class
4− MonadState
5− , get
6− , put
7− , state
8− , modify
9− , gets
10− -- * The State monad
11− , State
12− , runState
13− , evalState
14− , execState
15− -- * The StateT monad transformer
16− , StateT
17− , stateT
18− , runStateT
19− , evalStateT
20− , execStateT
21− -- * The State monad (lazy)
22− , LazyState
23− , runLazyState
24− , evalLazyState
25− , execLazyState
26− -- * The StateT monad transformer (lazy)
27− , LazyStateT
28− , lazyStateT
29− , runLazyStateT
30− , evalLazyStateT
31− , execLazyStateT
32− -- * The State monad (flattened)
33− , States
34− , runStates
35− -- * The StateT monad transformer (flattened)
36− , StatesT
37− , runStatesT
38− -- * MonadState class (implicit)
39− , MonadState'
40− , get'
41− , put'
42− , state'
43− , modify'
44− , gets'
45− -- * The State monad (implicit)
46− , State'
47− , runState'
48− , evalState'
49− , execState'
50− -- * The StateT monad transformer (implicit)
51− , StateT'
52− , stateT'
53− , runStateT'
54− , evalStateT'
55− , execStateT'
56− -- * The State monad (lazy, implicit)
57− , LazyState'
58− , runLazyState'
59− , evalLazyState'
60− , execLazyState'
61− -- * The StateT monad transformer (lazy, implicit)
62− , LazyStateT'
63− , lazyStateT'
64− , runLazyStateT'
65− , evalLazyStateT'
66− , execLazyStateT'
67− -- * Zoom
68− , ZoomT
69− , zoom
70− -- * Internal labels
71− , TAGGED
72− , STATE
73− , STATES
74− , ZOOM
75− ) where
76−
77−import qualified Control.Monad.State.Class as T
78−import qualified Control.Monad.Trans as Lift
79−import Control.Monad.Trans.Identity
80−import qualified Control.Monad.Trans.State.Lazy as T.Lazy
81−import qualified Control.Monad.Trans.State.Strict as T.Strict
82−import Data.Coerce
83−import Data.Functor.Identity
84−import Data.Kind
85−import Data.Proxy
86−import Data.Reflection
87−
88−import Ether.Internal
89−import Ether.TaggedTrans
90−
91−class Monad m => MonadState tag s m | m tag -> s where
92−
93− {-# MINIMAL state | get, put #-}
94−
95− -- | Return the state from the internals of the monad.
96− get :: m s
97− get = state @tag (\s -> (s, s))
98−
99− -- | Replace the state inside the monad.
100− put :: s -> m ()
101− put s = state @tag (\_ -> ((), s))
102−
103− -- | Embed a simple state action into the monad.
104− state :: (s -> (a, s)) -> m a
105− state f = do
106− s <- get @tag
107− let ~(a, s') = f s
108− put @tag s'
109− return a
110−
111−instance {-# OVERLAPPABLE #-}
112− ( Lift.MonadTrans t
113− , Monad (t m)
114− , MonadState tag s m
115− ) => MonadState tag s (t m)
116− where
117− get = Lift.lift (get @tag)
118− put = Lift.lift . put @tag
119− state = Lift.lift . state @tag
120−
121−instance {-# OVERLAPPABLE #-}
122− ( Monad (trans m)
123− , MonadState tag s (TaggedTrans effs trans m)
124− ) => MonadState tag s (TaggedTrans (eff ': effs) trans (m :: Type -> Type))
125− where
126−
127− get =
128− (coerce ::
129− TaggedTrans effs trans m s ->
130− TaggedTrans (eff ': effs) trans m s)
131− (get @tag)
132−
133− put =
134− (coerce ::
135− (s -> TaggedTrans effs trans m ()) ->
136− (s -> TaggedTrans (eff ': effs) trans m ()))
137− (put @tag)
138−
139− state =
140− (coerce :: forall a .
141− ((s -> (a, s)) -> TaggedTrans effs trans m a) ->
142− ((s -> (a, s)) -> TaggedTrans (eff ': effs) trans m a))
143− (state @tag)
144−
145−-- | Modifies the state inside a state monad.
146−modify :: forall tag s m . MonadState tag s m => (s -> s) -> m ()
147−modify f = state @tag (\s -> ((), f s))
148−
149−-- | Gets specific component of the state, using a projection function supplied.
150−gets :: forall tag s m a . MonadState tag s m => (s -> a) -> m a
151−gets f = fmap f (get @tag)
152−
153−-- | Encode type-level information for 'StateT'.
154−data STATE
155−
156−type instance HandleSuper STATE s trans = ()
157−type instance HandleConstraint STATE s trans m =
158− T.MonadState s (trans m)
159−
160−instance Handle STATE s (T.Strict.StateT s) where
161− handling r = r
162−
163−instance Handle STATE s (T.Lazy.StateT s) where
164− handling r = r
165−
166−instance
167− ( Handle STATE s trans
168− , Monad m, Monad (trans m)
169− ) => MonadState tag s (TaggedTrans (TAGGED STATE tag) trans m)
170− where
171−
172− get =
173− handling @STATE @s @trans @m $
174− coerce (T.get @s @(trans m))
175−
176− put =
177− handling @STATE @s @trans @m $
178− coerce (T.put @s @(trans m))
179−
180− state =
181− handling @STATE @s @trans @m $
182− coerce (T.state @s @(trans m) @a) ::
183− forall eff a . (s -> (a, s)) -> TaggedTrans eff trans m a
184−
185−instance
186− ( HasLens tag payload s
187− , Handle STATE payload trans
188− , Monad m, Monad (trans m)
189− ) => MonadState tag s (TaggedTrans (TAGGED STATE tag ': effs) trans m)
190− where
191−
192− get =
193− handling @STATE @payload @trans @m $
194− (coerce :: forall eff a .
195− trans m a ->
196− TaggedTrans eff trans m a)
197− (T.gets (view (lensOf @tag @payload @s)))
198−
199− put s =
200− handling @STATE @payload @trans @m $
201− (coerce :: forall eff a .
202− trans m a ->
203− TaggedTrans eff trans m a)
204− (T.modify (over (lensOf @tag @payload @s) (const s)))
205−
206− state f =
207− handling @STATE @payload @trans @m $
208− (coerce :: forall eff a .
209− trans m a ->
210− TaggedTrans eff trans m a)
211− (T.state (lensOf @tag @payload @s f))
212−
213−-- | The parametrizable state monad.
214−--
215−-- Computations have access to a mutable state.
216−--
217−-- The 'return' function leaves the state unchanged, while '>>=' uses
218−-- the final state of the first computation as the initial state of the second.
219−type State tag r = StateT tag r Identity
220−
221−-- | The state monad transformer.
222−--
223−-- The 'return' function leaves the state unchanged, while '>>=' uses
224−-- the final state of the first computation as the initial state of the second.
225−type StateT tag s = TaggedTrans (TAGGED STATE tag) (T.Strict.StateT s)
226−
227−-- | Constructor for computations in the state monad transformer.
228−stateT :: forall tag s m a . (s -> m (a, s)) -> StateT tag s m a
229−stateT = coerce (T.Strict.StateT @s @m @a)
230−
231−-- | Runs a 'StateT' with the given initial state
232−-- and returns both the final value and the final state.
233−runStateT :: forall tag s m a . StateT tag s m a -> s -> m (a, s)
234−runStateT = coerce (T.Strict.runStateT @s @m @a)
235−
236−-- | Runs a 'StateT' with the given initial state
237−-- and returns the final value, discarding the final state.
238−evalStateT :: forall tag s m a . Monad m => StateT tag s m a -> s -> m a
239−evalStateT = coerce (T.Strict.evalStateT @m @s @a)
240−
241−-- | Runs a 'StateT' with the given initial state
242−-- and returns the final state, discarding the final value.
243−execStateT :: forall tag s m a . Monad m => StateT tag s m a -> s -> m s
244−execStateT = coerce (T.Strict.execStateT @m @s @a)
245−
246−-- | Runs a 'State' with the given initial state
247−-- and returns both the final value and the final state.
248−runState :: forall tag s a . State tag s a -> s -> (a, s)
249−runState = coerce (T.Strict.runState @s @a)
250−
251−-- | Runs a 'State' with the given initial state
252−-- and returns the final value, discarding the final state.
253−evalState :: forall tag s a . State tag s a -> s -> a
254−evalState = coerce (T.Strict.evalState @s @a)
255−
256−-- | Runs a 'State' with the given initial state
257−-- and returns the final state, discarding the final value.
258−execState :: forall tag s a . State tag s a -> s -> s
259−execState = coerce (T.Strict.execState @s @a)
260−
261−-- | The parametrizable state monad.
262−--
263−-- Computations have access to a mutable state.
264−--
265−-- The 'return' function leaves the state unchanged, while '>>=' uses
266−-- the final state of the first computation as the initial state of the second.
267−type LazyState tag r = LazyStateT tag r Identity
268−
269−-- | The state monad transformer.
270−--
271−-- The 'return' function leaves the state unchanged, while '>>=' uses
272−-- the final state of the first computation as the initial state of the second.
273−type LazyStateT tag s = TaggedTrans (TAGGED STATE tag) (T.Lazy.StateT s)
274−
275−-- | Constructor for computations in the state monad transformer.
276−lazyStateT :: forall tag s m a . (s -> m (a, s)) -> LazyStateT tag s m a
277−lazyStateT = coerce (T.Lazy.StateT @s @m @a)
278−
279−-- | Runs a 'StateT' with the given initial state
280−-- and returns both the final value and the final state.
281−runLazyStateT :: forall tag s m a . LazyStateT tag s m a -> s -> m (a, s)
282−runLazyStateT = coerce (T.Lazy.runStateT @s @m @a)
283−
284−-- | Runs a 'StateT' with the given initial state
285−-- and returns the final value, discarding the final state.
286−evalLazyStateT :: forall tag s m a . Monad m => LazyStateT tag s m a -> s -> m a
287−evalLazyStateT = coerce (T.Lazy.evalStateT @m @s @a)
288−
289−-- | Runs a 'StateT' with the given initial state
290−-- and returns the final state, discarding the final value.
291−execLazyStateT :: forall tag s m a . Monad m => LazyStateT tag s m a -> s -> m s
292−execLazyStateT = coerce (T.Lazy.execStateT @m @s @a)
293−
294−-- | Runs a 'State' with the given initial state
295−-- and returns both the final value and the final state.
296−runLazyState :: forall tag s a . LazyState tag s a -> s -> (a, s)
297−runLazyState = coerce (T.Lazy.runState @s @a)
298−
299−-- | Runs a 'State' with the given initial state
300−-- and returns the final value, discarding the final state.
301−evalLazyState :: forall tag s a . LazyState tag s a -> s -> a
302−evalLazyState = coerce (T.Lazy.evalState @s @a)
303−
304−-- | Runs a 'State' with the given initial state
305−-- and returns the final state, discarding the final value.
306−execLazyState :: forall tag s a . LazyState tag s a -> s -> s
307−execLazyState = coerce (T.Lazy.execState @s @a)
308−
309−type family STATES (ts :: HList xs) :: [Type] where
310− STATES 'HNil = '[]
311− STATES ('HCons t ts) = TAGGED STATE t ': STATES ts
312−
313−type StatesT s = TaggedTrans (STATES (Tags s)) (T.Strict.StateT s)
314−
315−type States s = StatesT s Identity
316−
317−runStatesT :: forall p m a . StatesT p m a -> p -> m (a, p)
318−runStatesT = coerce (T.Strict.runStateT @p @m @a)
319−
320−runStates :: forall p a . States p a -> p -> (a, p)
321−runStates = coerce (T.Strict.runState @p @a)
322−
323−type StateT' s = StateT s s
324−
325−stateT' :: (s -> m (a, s)) -> StateT' s m a
326−stateT' = stateT
327−
328−runStateT' :: StateT' s m a -> s -> m (a, s)
329−runStateT' = runStateT
330−
331−runState' :: State' s a -> s -> (a, s)
332−runState' = runState
333−
334−evalStateT' :: Monad m => StateT' s m a -> s -> m a
335−evalStateT' = evalStateT
336−
337−type State' s = State s s
338−
339−evalState' :: State' s a -> s -> a
340−evalState' = evalState
341−
342−execStateT' :: Monad m => StateT' s m a -> s -> m s
343−execStateT' = execStateT
344−
345−execState' :: State' s a -> s -> s
346−execState' = execState
347−
348−type LazyStateT' s = LazyStateT s s
349−
350−lazyStateT' :: (s -> m (a, s)) -> LazyStateT' s m a
351−lazyStateT' = lazyStateT
352−
353−runLazyStateT' :: LazyStateT' s m a -> s -> m (a, s)
354−runLazyStateT' = runLazyStateT
355−
356−runLazyState' :: LazyState' s a -> s -> (a, s)
357−runLazyState' = runLazyState
358−
359−evalLazyStateT' :: Monad m => LazyStateT' s m a -> s -> m a
360−evalLazyStateT' = evalLazyStateT
361−
362−type LazyState' s = LazyState s s
363−
364−evalLazyState' :: LazyState' s a -> s -> a
365−evalLazyState' = evalLazyState
366−
367−execLazyStateT' :: Monad m => LazyStateT' s m a -> s -> m s
368−execLazyStateT' = execLazyStateT
369−
370−execLazyState' :: LazyState' s a -> s -> s
371−execLazyState' = execLazyState
372−
373−type MonadState' s = MonadState s s
374−
375−get' :: forall s m . MonadState' s m => m s
376−get' = get @s
377−
378−gets' :: forall s m a . MonadState' s m => (s -> a) -> m a
379−gets' = gets @s
380−
381−put' :: forall s m . MonadState' s m => s -> m ()
382−put' = put @s
383−
384−state' :: forall s m a . MonadState' s m => (s -> (a, s)) -> m a
385−state' = state @s
386−
387−modify' :: forall s m . MonadState' s m => (s -> s) -> m ()
388−modify' = modify @s
389−
390−-- | Encode type-level information for 'zoom'.
391−data ZOOM t z
392−
393−type ZoomT t (z :: Type) = TaggedTrans (ZOOM t z) IdentityT
394−
395−-- | Zoom into a part of a state using a lens.
396−zoom
397− :: forall tag sOuter sInner m a
398− . Lens' sOuter sInner
399− -> (forall z . Reifies z (ReifiedLens' sOuter sInner) => ZoomT tag z m a)
400− -> m a
401−zoom l m = reify (Lens l) (\(_ :: Proxy z) -> coerce (m @z))
402−
403−instance
404− ( MonadState tag sOuter m
405− , Reifies z (ReifiedLens' sOuter sInner)
406− , trans ~ IdentityT
407− ) => MonadState tag sInner (TaggedTrans (ZOOM tag z) trans m)
408− where
409− state =
410− (coerce :: forall eff r a .
411− (r -> m a) ->
412− (r -> TaggedTrans eff trans m a))
413− (state @tag . l)
414− where
415− Lens l = reflect (Proxy :: Proxy z)
src/Ether/TagDispatch.hsdeleted−138
@@ -1,138 +0,0 @@
1−{- |
2−
3−Type-level machinery to manipulate constraints on the monad
4−transformer stack.
5−
6−Out of the box it provides the following dispatch strategies:
7−
8−* 'tagAttach' to use functions defined using untagged monad classes
9− as if they were defined using tagged ones.
10−
11−* 'tagReplace' to use functions defined using one tag
12− as if they were defined using another one.
13−
14−> import Ether
15−> import Control.Monad.State as Mtl
16−>
17−> data Foo
18−> data Bar
19−>
20−> f :: Mtl.MonadState Int m => m String
21−> f = fmap show Mtl.get
22−>
23−> g :: Ether.MonadState Foo Int m => m String
24−> g = tagAttach @Foo f
25−>
26−> h :: Ether.MonadState Bar Int m => m String
27−> h = tagReplace @Foo @Bar g
28−
29−-}
30−
31−module Ether.TagDispatch
32− (
33− -- * The Tag Attach monad transformer
34− TagAttachT
35− , tagAttach
36− -- * The Tag Replace monad transformer
37− , TagReplaceT
38− , tagReplace
39− -- * Internal labels
40− , TAG_ATTACH
41− , TAG_REPLACE
42− ) where
43−
44−import qualified Control.Monad.Error.Class as Mtl
45−import qualified Control.Monad.Reader.Class as Mtl
46−import qualified Control.Monad.State.Class as Mtl
47−import qualified Control.Monad.Writer.Class as Mtl
48−
49−import Ether.Except
50−import Ether.Reader
51−import Ether.State
52−import Ether.Writer
53−import Ether.TaggedTrans
54−
55−import Control.Monad.Trans.Identity
56−import Data.Coerce
57−
58−-- | Encode type-level information for 'tagAttach'.
59−data TAG_ATTACH t
60−
61−type TagAttachT t = TaggedTrans (TAG_ATTACH t) IdentityT
62−
63−-- | Attach a tag to untagged transformers.
64−tagAttach :: forall tag m a . TagAttachT tag m a -> m a
65−tagAttach = coerce (runIdentityT @_ @m @a)
66−
67−instance {-# OVERLAPPING #-}
68− ( MonadReader tag r m, trans ~ IdentityT
69− ) => Mtl.MonadReader r (TaggedTrans (TAG_ATTACH tag) trans m)
70− where
71− ask = ask @tag
72− local = local @tag
73− reader = reader @tag
74−
75−instance {-# OVERLAPPING #-}
76− ( MonadState tag s m, trans ~ IdentityT
77− ) => Mtl.MonadState s (TaggedTrans (TAG_ATTACH tag) trans m)
78− where
79− get = get @tag
80− put = put @tag
81− state = state @tag
82−
83−instance {-# OVERLAPPING #-}
84− ( MonadExcept tag e m, trans ~ IdentityT
85− ) => Mtl.MonadError e (TaggedTrans (TAG_ATTACH tag) trans m)
86− where
87− throwError = throw @tag
88− catchError = catch @tag
89−
90−instance {-# OVERLAPPING #-}
91− ( MonadWriter tag w m, trans ~ IdentityT
92− ) => Mtl.MonadWriter w (TaggedTrans (TAG_ATTACH tag) trans m)
93− where
94− writer = writer @tag
95− tell = tell @tag
96− listen = listen @tag
97− pass = pass @tag
98−
99−-- | Encode type-level information for 'tagReplace'.
100−data TAG_REPLACE tOld tNew
101−
102−type TagReplaceT tOld tNew = TaggedTrans (TAG_REPLACE tOld tNew) IdentityT
103−
104−-- | Replace a tag with another tag.
105−tagReplace :: forall tOld tNew m a . TagReplaceT tOld tNew m a -> m a
106−tagReplace = coerce (runIdentityT @_ @m @a)
107−
108−instance
109− ( MonadReader tNew r m, trans ~ IdentityT
110− ) => MonadReader tOld r (TaggedTrans (TAG_REPLACE tOld tNew) trans m)
111− where
112− ask = ask @tNew
113− local = local @tNew
114− reader = reader @tNew
115−
116−instance
117− ( MonadState tNew s m, trans ~ IdentityT
118− ) => MonadState tOld s (TaggedTrans (TAG_REPLACE tOld tNew) trans m)
119− where
120− get = get @tNew
121− put = put @tNew
122− state = state @tNew
123−
124−instance
125− ( MonadExcept tNew e m, trans ~ IdentityT
126− ) => MonadExcept tOld e (TaggedTrans (TAG_REPLACE tOld tNew) trans m)
127− where
128− throw = throw @tNew
129− catch = catch @tNew
130−
131−instance
132− ( MonadWriter tNew w m, trans ~ IdentityT
133− ) => MonadWriter tOld w (TaggedTrans (TAG_REPLACE tOld tNew) trans m)
134− where
135− writer = writer @tNew
136− tell = tell @tNew
137− listen = listen @tNew
138− pass = pass @tNew
src/Ether/TaggedTrans.hsdeleted−206
@@ -1,206 +0,0 @@
1−-- The use of ImpredicativeTypes here is safe, see discussion under GitHub issue
2−-- #35. It's only needed to allow the visible type application of a polytype.
3−{-# LANGUAGE ImpredicativeTypes #-}
4−
5−module Ether.TaggedTrans
6− ( TaggedTrans(..)
7− ) where
8−
9−import Control.Applicative
10−import Control.Monad (MonadPlus)
11−import Control.Monad.Fix (MonadFix)
12−import Control.Monad.Trans.Class (MonadTrans, lift)
13−import Control.Monad.IO.Class (MonadIO)
14−import Control.Monad.Morph (MFunctor(..), MMonad(..))
15−import Control.Monad.Catch (MonadThrow, MonadCatch, MonadMask)
16−
17−import qualified Control.Monad.Base as MB
18−import qualified Control.Monad.Trans.Control as MC
19−
20−import qualified Control.Monad.Trans.Lift.StT as Lift
21−import qualified Control.Monad.Trans.Lift.Local as Lift
22−import qualified Control.Monad.Trans.Lift.Catch as Lift
23−import qualified Control.Monad.Trans.Lift.Listen as Lift
24−import qualified Control.Monad.Trans.Lift.Pass as Lift
25−import qualified Control.Monad.Trans.Lift.CallCC as Lift
26−
27−import qualified Control.Monad.Cont.Class as Mtl
28−import qualified Control.Monad.Reader.Class as Mtl
29−import qualified Control.Monad.State.Class as Mtl
30−import qualified Control.Monad.Writer.Class as Mtl
31−import qualified Control.Monad.Error.Class as Mtl
32−
33−import GHC.Generics (Generic)
34−import Data.Coerce (coerce)
35−
36−newtype TaggedTrans tag trans m a = TaggedTrans (trans m a)
37− deriving
38− ( Generic
39− , Functor, Applicative, Alternative, Monad, MonadPlus
40− , MonadFix, MonadTrans, MonadIO
41− , MonadThrow, MonadCatch, MonadMask )
42−
43−type Pack tag trans m a = trans m a -> TaggedTrans tag trans m a
44−
45−type Unpack tag trans m a = TaggedTrans tag trans m a -> trans m a
46−
47−instance
48− ( MB.MonadBase b (trans m)
49− ) => MB.MonadBase b (TaggedTrans tag trans m)
50− where
51− liftBase =
52− (coerce :: forall a .
53− (b a -> trans m a) ->
54− (b a -> TaggedTrans tag trans m a))
55− MB.liftBase
56−
57−instance
58− ( MC.MonadTransControl trans
59− ) => MC.MonadTransControl (TaggedTrans tag trans)
60− where
61− type StT (TaggedTrans tag trans) a = MC.StT trans a
62−
63− liftWith = MC.defaultLiftWith
64− (coerce :: Pack tag trans m a)
65− (coerce :: Unpack tag trans m a)
66−
67− restoreT = MC.defaultRestoreT
68− (coerce :: Pack tag trans m a)
69−
70−type LiftBaseWith b m a = (MC.RunInBase m b -> b a) -> m a
71−
72−newtype LiftBaseWith' b m a = LBW { unLBW :: LiftBaseWith b m a }
73−
74−coerceLiftBaseWith ::
75− LiftBaseWith b (trans m) a ->
76− LiftBaseWith b (TaggedTrans tag trans m) a
77−coerceLiftBaseWith lbw =
78− unLBW (coerce (LBW lbw))
79−
80−instance
81− ( MC.MonadBaseControl b (trans m)
82− ) => MC.MonadBaseControl b (TaggedTrans tag trans m)
83− where
84− type StM (TaggedTrans tag trans m) a = MC.StM (trans m) a
85−
86− liftBaseWith = coerceLiftBaseWith MC.liftBaseWith
87−
88− restoreM =
89− (coerce :: forall a .
90− (MC.StM (trans m) a -> trans m a) ->
91− (MC.StM (trans m) a -> TaggedTrans tag trans m a))
92− MC.restoreM
93−
94−type instance Lift.StT (TaggedTrans tag trans) a = Lift.StT trans a
95−
96−instance Lift.LiftLocal trans => Lift.LiftLocal (TaggedTrans tag trans) where
97− liftLocal =
98− Lift.defaultLiftLocal
99− (coerce :: Pack tag trans m a)
100− (coerce :: Unpack tag trans m a)
101−
102−instance Lift.LiftCatch trans => Lift.LiftCatch (TaggedTrans tag trans) where
103− liftCatch =
104− Lift.defaultLiftCatch
105− (coerce :: Pack tag trans m a)
106− (coerce :: Unpack tag trans m a)
107−
108−instance Lift.LiftListen trans => Lift.LiftListen (TaggedTrans tag trans) where
109− liftListen =
110− Lift.defaultLiftListen
111− (coerce :: Pack tag trans m a)
112− (coerce :: Unpack tag trans m a)
113−
114−instance Lift.LiftPass trans => Lift.LiftPass (TaggedTrans tag trans) where
115− liftPass =
116− Lift.defaultLiftPass
117− (coerce :: Pack tag trans m a)
118− (coerce :: Unpack tag trans m a)
119−
120−instance Lift.LiftCallCC trans => Lift.LiftCallCC (TaggedTrans tag trans) where
121− liftCallCC =
122− Lift.defaultLiftCallCC
123− (coerce :: Pack tag trans m a)
124− (coerce :: Unpack tag trans m a)
125− liftCallCC' =
126− Lift.defaultLiftCallCC'
127− (coerce :: Pack tag trans m a)
128− (coerce :: Unpack tag trans m a)
129−
130−
131−-- Instances for mtl classes
132−
133−instance
134− ( Mtl.MonadCont m
135− , Lift.LiftCallCC trans
136− , Monad (trans m)
137− ) => Mtl.MonadCont (TaggedTrans tag trans m)
138− where
139− callCC = Lift.liftCallCC' Mtl.callCC
140−
141−instance
142− ( Mtl.MonadReader r m
143− , Lift.LiftLocal trans
144− , Monad (trans m)
145− ) => Mtl.MonadReader r (TaggedTrans tag trans m)
146− where
147− ask = lift Mtl.ask
148− local = Lift.liftLocal Mtl.ask Mtl.local
149− reader = lift . Mtl.reader
150−
151−instance
152− ( Mtl.MonadState s m
153− , MonadTrans trans
154− , Monad (trans m)
155− ) => Mtl.MonadState s (TaggedTrans tag trans m)
156− where
157− get = lift Mtl.get
158− put = lift . Mtl.put
159− state = lift . Mtl.state
160−
161−instance
162− ( Mtl.MonadWriter w m
163− , Lift.LiftListen trans
164− , Lift.LiftPass trans
165− , Monad (trans m)
166− ) => Mtl.MonadWriter w (TaggedTrans tag trans m)
167− where
168− writer = lift . Mtl.writer
169− tell = lift . Mtl.tell
170− listen = Lift.liftListen Mtl.listen
171− pass = Lift.liftPass Mtl.pass
172−
173−instance
174− ( Mtl.MonadError e m
175− , Lift.LiftCatch trans
176− , Monad (trans m)
177− ) => Mtl.MonadError e (TaggedTrans tag trans m)
178− where
179− throwError = lift . Mtl.throwError
180− catchError = Lift.liftCatch Mtl.catchError
181−
182−type Hoist trans =
183− forall m n b . Monad m =>
184− (forall a . m a -> n a) -> trans m b -> trans n b
185−
186−-- NB: Don't use GeneralizedNewtypeDeriving to create this instance, as it will
187−-- trigger GHC Trac #11837 on GHC 8.0.1 and older.
188−instance MFunctor trans => MFunctor (TaggedTrans tag trans) where
189− hoist =
190− coerce
191− @(Hoist trans)
192− @(Hoist (TaggedTrans tag trans))
193− hoist
194−
195−type Embed trans =
196− forall n m b . Monad n =>
197− (forall a . m a -> trans n a) -> trans m b -> trans n b
198−
199−-- NB: Don't use GeneralizedNewtypeDeriving to create this instance, as it will
200−-- trigger GHC Trac #11837 on GHC 8.0.1 and older.
201−instance MMonad trans => MMonad (TaggedTrans tag trans) where
202− embed =
203− coerce
204− @(Embed trans)
205− @(Embed (TaggedTrans tag trans))
206− embed
src/Ether/Writer.hsdeleted−287
@@ -1,287 +0,0 @@
1−module Ether.Writer
2− (
3− -- * MonadWriter class
4− MonadWriter
5− , writer
6− , tell
7− , listen
8− , pass
9− , listens
10− , censor
11− -- * The Writer monad
12− , Writer
13− , runWriter
14− , execWriter
15− -- * The WriterT monad transformer
16− , WriterT
17− , writerT
18− , runWriterT
19− , execWriterT
20− -- * The Writer monad (lazy)
21− , LazyWriter
22− , runLazyWriter
23− , execLazyWriter
24− -- * The WriterT monad transformer (lazy)
25− , LazyWriterT
26− , lazyWriterT
27− , runLazyWriterT
28− , execLazyWriterT
29− -- * MonadWriter class (implicit)
30− , MonadWriter'
31− , writer'
32− , tell'
33− , listen'
34− , pass'
35− , listens'
36− , censor'
37− -- * The Writer monad (implicit)
38− , Writer'
39− , runWriter'
40− , execWriter'
41− -- * The WriterT monad transformer (implicit)
42− , WriterT'
43− , writerT'
44− , runWriterT'
45− , execWriterT'
46− -- * The Writer monad (lazy, implicit)
47− , LazyWriter'
48− , runLazyWriter'
49− , execLazyWriter'
50− -- * The WriterT monad transformer (lazy, implicit)
51− , LazyWriterT'
52− , lazyWriterT'
53− , runLazyWriterT'
54− , execLazyWriterT'
55− -- * Internal labels
56− , TAGGED
57− , WRITER
58− ) where
59−
60−import Control.Monad.Signatures (Listen, Pass)
61−import qualified Control.Monad.Trans.Lift.Listen as Lift
62−import qualified Control.Monad.Trans.Lift.Pass as Lift
63−import qualified Control.Monad.Writer.Class as T
64−import qualified Control.Monad.Writer.CPS as T.CPS
65−import qualified Control.Monad.Writer.Lazy as T.Lazy
66−import Data.Coerce
67−import Data.Functor.Identity
68−
69−import Ether.Internal
70−import Ether.TaggedTrans
71−
72−class (Monoid w, Monad m) => MonadWriter tag w m | m tag -> w where
73−
74− {-# MINIMAL (writer | tell), listen, pass #-}
75−
76− -- | Embed a simple writer action.
77− writer :: (a, w) -> m a
78− writer ~(a, w) = a <$ tell @tag w
79−
80− -- | Append a value to the accumulator within the monad.
81− tell :: w -> m ()
82− tell w = writer @tag ((),w)
83−
84− -- | Execute an action and add its accumulator
85− -- to the value of the computation.
86− listen :: m a -> m (a, w)
87−
88− -- | Execute an action which returns a value and a function,
89− -- and return the value, applying the function to the accumulator.
90− pass :: m (a, w -> w) -> m a
91−
92−instance {-# OVERLAPPABLE #-}
93− ( Lift.LiftListen t
94− , Lift.LiftPass t
95− , Monad (t m)
96− , MonadWriter tag w m
97− , Monoid w
98− ) => MonadWriter tag w (t m) where
99− writer = Lift.lift . writer @tag
100− tell = Lift.lift . tell @tag
101− listen = Lift.liftListen (listen @tag)
102− pass = Lift.liftPass (pass @tag)
103−
104−-- | Execute an action and add the result of applying the given function to
105−-- its accumulator to the value of the computation.
106−listens :: forall tag w m a b . MonadWriter tag w m => (w -> b) -> m a -> m (a, b)
107−listens f m = do
108− ~(a, w) <- listen @tag m
109− return (a, f w)
110−
111−-- | Execute an action and apply a function to its accumulator.
112−censor :: forall tag w m a . MonadWriter tag w m => (w -> w) -> m a -> m a
113−censor f m = pass @tag $ do
114− a <- m
115− return (a, f)
116−
117−-- | Encode type-level information for 'WriterT'.
118−data WRITER
119−
120−type instance HandleSuper WRITER w trans = Monoid w
121−type instance HandleConstraint WRITER w trans m =
122− T.MonadWriter w (trans m)
123−
124−instance Monoid w => Handle WRITER w (T.CPS.WriterT w) where
125− handling r = r
126−
127−instance Monoid w => Handle WRITER w (T.Lazy.WriterT w) where
128− handling r = r
129−
130−instance
131− ( Handle WRITER w trans
132− , Monad m, Monad (trans m)
133− ) => MonadWriter tag w (TaggedTrans (TAGGED WRITER tag) trans m)
134− where
135−
136− writer =
137− handling @WRITER @w @trans @m $
138− coerce (T.writer @w @(trans m) @a) ::
139− forall eff a . (a, w) -> TaggedTrans eff trans m a
140−
141− tell =
142− handling @WRITER @w @trans @m $
143− coerce (T.tell @w @(trans m))
144−
145− listen =
146− handling @WRITER @w @trans @m $
147− coerce (T.listen @w @(trans m) @a) ::
148− forall eff a . Listen w (TaggedTrans eff trans m) a
149−
150− pass =
151− handling @WRITER @w @trans @m $
152− coerce (T.pass @w @(trans m) @a) ::
153− forall eff a . Pass w (TaggedTrans eff trans m) a
154−
155−-- | The parametrizable writer monad.
156−--
157−-- Computations can accumulate a monoid value.
158−--
159−-- The 'return' function produces the output 'mempty', while '>>=' combines
160−-- the outputs of the subcomputations using 'mappend'.
161−type Writer tag w = WriterT tag w Identity
162−
163−-- | The writer monad transformer.
164−--
165−-- The 'return' function produces the output 'mempty', while '>>=' combines
166−-- the outputs of the subcomputations using 'mappend'.
167−type WriterT tag w = TaggedTrans (TAGGED WRITER tag) (T.CPS.WriterT w)
168−
169−-- | Constructor for computations in the writer monad transformer.
170−writerT :: forall tag w m a . (Functor m, Monoid w) => m (a, w) -> WriterT tag w m a
171−writerT = coerce (T.CPS.writerT @m @w @a)
172−
173−-- | Runs a 'WriterT' and returns both the normal value
174−-- and the final accumulator.
175−runWriterT :: forall tag w m a . Monoid w => WriterT tag w m a -> m (a, w)
176−runWriterT = coerce (T.CPS.runWriterT @w @m @a)
177−
178−-- | Runs a 'Writer' and returns both the normal value
179−-- and the final accumulator.
180−runWriter :: forall tag w a . Monoid w => Writer tag w a -> (a, w)
181−runWriter = coerce (T.CPS.runWriter @w @a)
182−
183−-- | Runs a 'WriterT' and returns the final accumulator,
184−-- discarding the normal value.
185−execWriterT :: forall tag w m a . (Monad m, Monoid w) => WriterT tag w m a -> m w
186−execWriterT = coerce (T.CPS.execWriterT @m @w @a)
187−
188−-- | Runs a 'Writer' and returns the final accumulator,
189−-- discarding the normal value.
190−execWriter :: forall tag w a . Monoid w => Writer tag w a -> w
191−execWriter = coerce (T.CPS.execWriter @w @a)
192−
193−-- | The parametrizable writer monad.
194−--
195−-- Computations can accumulate a monoid value.
196−--
197−-- The 'return' function produces the output 'mempty', while '>>=' combines
198−-- the outputs of the subcomputations using 'mappend'.
199−type LazyWriter tag w = LazyWriterT tag w Identity
200−
201−-- | The writer monad transformer.
202−--
203−-- The 'return' function produces the output 'mempty', while '>>=' combines
204−-- the outputs of the subcomputations using 'mappend'.
205−type LazyWriterT tag w = TaggedTrans (TAGGED WRITER tag) (T.Lazy.WriterT w)
206−
207−-- | Constructor for computations in the writer monad transformer.
208−lazyWriterT :: forall tag w m a . m (a, w) -> LazyWriterT tag w m a
209−lazyWriterT = coerce (T.Lazy.WriterT @w @m @a)
210−
211−-- | Runs a 'WriterT' and returns both the normal value
212−-- and the final accumulator.
213−runLazyWriterT :: forall tag w m a . LazyWriterT tag w m a -> m (a, w)
214−runLazyWriterT = coerce (T.Lazy.runWriterT @w @m @a)
215−
216−-- | Runs a 'Writer' and returns both the normal value
217−-- and the final accumulator.
218−runLazyWriter :: forall tag w a . LazyWriter tag w a -> (a, w)
219−runLazyWriter = coerce (T.Lazy.runWriter @w @a)
220−
221−-- | Runs a 'WriterT' and returns the final accumulator,
222−-- discarding the normal value.
223−execLazyWriterT :: forall tag w m a . Monad m => LazyWriterT tag w m a -> m w
224−execLazyWriterT = coerce (T.Lazy.execWriterT @m @w @a)
225−
226−-- | Runs a 'Writer' and returns the final accumulator,
227−-- discarding the normal value.
228−execLazyWriter :: forall tag w a . LazyWriter tag w a -> w
229−execLazyWriter = coerce (T.Lazy.execWriter @w @a)
230−
231−type Writer' w = Writer w w
232−
233−runWriter' :: Monoid w => Writer' w a -> (a, w)
234−runWriter' = runWriter
235−
236−execWriter' :: Monoid w => Writer' w a -> w
237−execWriter' = execWriter
238−
239−type WriterT' w = WriterT w w
240−
241−writerT' :: (Functor m, Monoid w) => m (a, w) -> WriterT' w m a
242−writerT' = writerT
243−
244−runWriterT' :: Monoid w => WriterT' w m a -> m (a, w)
245−runWriterT' = runWriterT
246−
247−execWriterT' :: (Monad m, Monoid w) => WriterT' w m a -> m w
248−execWriterT' = execWriterT
249−
250−type LazyWriter' w = LazyWriter w w
251−
252−runLazyWriter' :: LazyWriter' w a -> (a, w)
253−runLazyWriter' = runLazyWriter
254−
255−execLazyWriter' :: LazyWriter' w a -> w
256−execLazyWriter' = execLazyWriter
257−
258−type LazyWriterT' w = LazyWriterT w w
259−
260−lazyWriterT' :: m (a, w) -> LazyWriterT' w m a
261−lazyWriterT' = lazyWriterT
262−
263−runLazyWriterT' :: LazyWriterT' w m a -> m (a, w)
264−runLazyWriterT' = runLazyWriterT
265−
266−execLazyWriterT' :: Monad m => LazyWriterT' w m a -> m w
267−execLazyWriterT' = execLazyWriterT
268−
269−type MonadWriter' w = MonadWriter w w
270−
271−writer' :: forall w m a . MonadWriter' w m => (a, w) -> m a
272−writer' = writer @w
273−
274−tell' :: forall w m . MonadWriter' w m => w -> m ()
275−tell' = tell @w
276−
277−listen' :: forall w m a . MonadWriter' w m => m a -> m (a, w)
278−listen' = listen @w
279−
280−pass' :: forall w m a . MonadWriter' w m => m (a, w -> w) -> m a
281−pass' = pass @w
282−
283−listens' :: forall w m a b . MonadWriter' w m => (w -> b) -> m a -> m (a, b)
284−listens' = listens @w
285−
286−censor' :: forall w m a . MonadWriter' w m => (w -> w) -> m a -> m a
287−censor' = censor @w
test/Regression.hs+174−25
@@ -1,35 +1,184 @@
1+{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE FlexibleContexts #-}
3+{-# LANGUAGE EmptyDataDecls #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE ConstraintKinds #-}
6+{-# LANGUAGE ScopedTypeVariables #-}
7+{-# LANGUAGE LambdaCase #-}
18module Main where
29
10+import Data.Functor.Identity
11+import Control.Ether.Tags
12+import Control.Ether.TH
13+import Control.Ether.Wrapped
14+import Control.Monad.Ether.Reader
15+import Control.Monad.Ether.State
16+import Control.Monad.Ether.Implicit.Except.TH
17+import qualified Control.Monad.Ether.Implicit.Reader as I
18+import qualified Control.Monad.Ether.Implicit.State as I
19+import qualified Control.Monad.Ether.Implicit.Except as I
20+import qualified Control.Monad.Reader as T
21+import qualified Control.Monad.State as T
22+
323import Test.Tasty
24+import Test.Tasty.QuickCheck
25+import Test.QuickCheck.Function
426
5−import Regression.T1
6−import Regression.T2
7−import Regression.T3
8−import Regression.T4
9−import Regression.T5
10−import Regression.T6
11−import Regression.T7
12−import Regression.T8
13−import Regression.T9
14−import Regression.T10
15−import Regression.T11
16−import Regression.T12
27+ethereal "R1" "r1"
28+ethereal "R2" "r2"
29+ethereal "S1" "s1"
1730
1831main :: IO ()
1932main = defaultMain suite
2033
2134suite :: TestTree
2235suite = testGroup "Ether"
23− [ test1
24− , test2
25− , test3
26− , test4
27− , test5
28− , test6
29− , test7
30− , test8
31− , test9
32− , test10
33− , test11
34− , test12
35− ]
36+ [ testGroup "ReaderT"
37+ [ testProperty "layered sum (local left)" layeredLocalLeft
38+ , testProperty "layered sum (local right)" layeredLocalRight
39+ ]
40+ ]
41+
42+layeredLocalLeft, layeredLocalRight
43+ :: Fun (Int, Integer) Integer
44+ -> Fun Integer Integer
45+ -> Int -> Integer -> Property
46+
47+layeredLocalLeft k f a1 a2 = property (direct == run indirect)
48+ where
49+ run = flip (runReader r1) a1 . flip (runReaderT r2) a2
50+ (direct, indirect) = layeredLocalCore' k f a1 a2
51+
52+layeredLocalRight k f a1 a2 = property (direct == run indirect)
53+ where
54+ run = flip (runReader r2) a2 . flip (runReaderT r1) a1
55+ (direct, indirect) = layeredLocalCore' k f a1 a2
56+
57+layeredLocalCore
58+ :: (MonadReader R1 r1 m, MonadReader R2 r2 m)
59+ => (r2 -> r2) -> (r1 -> r2 -> a) -> m a
60+layeredLocalCore f g = do
61+ n <- ask r1
62+ m <- local r2 f (ask r2)
63+ return (g n m)
64+
65+layeredLocalCore'
66+ :: (MonadReader R1 Int m, MonadReader R2 Integer m)
67+ => Fun (Int, Integer) Integer
68+ -> Fun Integer Integer
69+ -> Int -> Integer -> (Integer, m Integer)
70+layeredLocalCore' k f a1 a2 = (direct, indirect)
71+ where
72+ direct = apply k (fromIntegral a1, apply f a2)
73+ indirect = layeredLocalCore (apply f) (\n m -> apply k (fromIntegral n, m))
74+
75+implicitCore :: (I.MonadReader Int m, I.MonadReader Bool m) => m String
76+implicitCore = I.local (succ :: Int -> Int) $ do
77+ n :: Int <- I.ask
78+ b <- I.local not I.ask
79+ return (if b then "" else show n)
80+
81+wrapCore
82+ :: ( T.MonadReader Int m
83+ , T.MonadState Int m
84+ ) => m Int
85+wrapCore = do
86+ b <- T.get
87+ a <- T.ask
88+ T.put (a + b)
89+ return (a * b)
90+
91+wrapCore'
92+ :: ( MonadReader S1 Int m
93+ , MonadState S1 Int m
94+ , MonadReader R1 Int m
95+ ) => m Int
96+wrapCore' = do
97+ a <- ethered s1 wrapCore
98+ c <- ask r1
99+ return (a + c)
100+
101+wrapCore'' :: Int -> (Int, Int)
102+wrapCore'' a = runReader r1 (runStateT s1 (runReaderT s1 wrapCore' a) a) (-1)
103+
104+-- Should not compile with `ensureUniqueTags`
105+uniqueTagsCore :: IO ()
106+uniqueTagsCore = flip (runReaderT r1) (1 :: Int)
107+ . flip (runReaderT r1) (True :: Bool)
108+ . flip (runReaderT r1) (2 :: Int)
109+ . flip (runReaderT r1) (3 :: Integer)
110+ {- . ensureUniqueTags -}
111+ $ do
112+ a :: Integer <- ask r1
113+ b :: Int <- ask r1
114+ c :: Bool <- ask r1
115+ T.liftIO $ do
116+ print a
117+ print b
118+ print c
119+
120+stateCore :: ( MonadState S1 Int m
121+ , MonadReader R1 Int m
122+ , UniqueTags m ) => m ()
123+stateCore = do
124+ a <- ask r1
125+ n <- get s1
126+ put s1 (n * a)
127+ modify s1 (subtract 1)
128+
129+recurseCore :: (Num a, Ord a) => (I.MonadReader a m, I.MonadState Int m) => m a
130+recurseCore = do
131+ a <- I.ask
132+ if (a <= 0)
133+ then do
134+ I.put (0 :: Int)
135+ return 1
136+ else do
137+ I.modify (succ :: Int -> Int)
138+ b <- I.runReaderT recurseCore (a - 1)
139+ I.modify (succ :: Int -> Int)
140+ return (a * b)
141+
142+factorial :: (Num a, Ord a) => a -> (a, Int)
143+factorial a = I.runState (I.runReaderT recurseCore a) (0 :: Int)
144+
145+factorial' :: Int -> (Int, Int)
146+factorial' a = factorial (a :: Int)
147+
148+data DivideByZero = DivideByZero
149+ deriving (Show)
150+data NegativeLog = NegativeLog
151+ deriving (Show)
152+
153+exceptCore
154+ :: ( Floating a, Ord a
155+ , I.MonadExcept DivideByZero m
156+ , I.MonadExcept NegativeLog m
157+ ) => a -> a -> m a
158+exceptCore a b = do
159+ if b == 0
160+ then I.throw DivideByZero
161+ else
162+ let d = a /b
163+ in if d < 0
164+ then I.throw NegativeLog
165+ else return $ log (a / b)
166+
167+try0 :: m a -> m a
168+try0 = $(try 0)
169+
170+try1 :: Functor m => I.ExceptT e m a -> (e -> a) -> m a
171+try1 = $(try 1)
172+
173+try2 :: Functor m => I.ExceptT e1 (I.ExceptT e2 m) a -> (e1 -> a) -> (e2 -> a) -> m a
174+try2 = $(try 2)
175+
176+try3 :: Functor m => I.ExceptT e1 (I.ExceptT e2 (I.ExceptT e3 m)) a -> (e1 -> a) -> (e2 -> a) -> (e3 -> a) -> m a
177+try3 = $(try 3)
178+
179+exceptCore' :: Double -> Double -> String
180+exceptCore' a b = runIdentity $ do
181+ $(try 2)
182+ (show <$> exceptCore a b)
183+ (\NegativeLog -> "nl")
184+ (\DivideByZero -> "dz")
test/Regression/T1.hsdeleted−50
@@ -1,50 +0,0 @@
1−module Regression.T1 (test1) where
2−
3−import Ether
4−import TupleInstances ()
5−import Data.List (group)
6−
7−import Test.Tasty
8−import Test.Tasty.QuickCheck
9−
10−data Tag1
11−data Tag2
12−
13−testEther
14− :: (MonadReader Tag1 String m, MonadReader Tag2 String m)
15− => m ((String, String), (String, String))
16−testEther = do
17− s1 <- ask @Tag1
18− s2 <- ask @Tag2
19− let s1s2 = (s1, s2)
20− s1s2' <- local @Tag2 (map succ) $ do
21− s1' <- ask @Tag1
22− s2' <- ask @Tag2
23− return (s1', s2')
24− return (s1s2, s1s2')
25−
26−runner1 s1 s2 = flip (runReader @Tag1) s1 . flip (runReaderT @Tag2) s2
27−runner2 s1 s2 = flip (runReader @Tag2) s2 . flip (runReaderT @Tag1) s1
28−runner3 s1 s2 = flip runReaders (Tagged @Tag1 s1, Tagged @Tag2 s2)
29−
30−same :: Eq a => [a] -> Bool
31−same = (<=1) . length . group
32−
33−test1 :: TestTree
34−test1 = testGroup "T1: Reader local environment"
35− [ testProperty "runner₁ works"
36− $ \s1 s2 -> property
37− $ runner1 s1 s2 testEther == ((s1, s2), (s1, map succ s2))
38− , testProperty "runner₂ works"
39− $ \s1 s2 -> property
40− $ runner2 s1 s2 testEther == ((s1, s2), (s1, map succ s2))
41− , testProperty "runner₃ works"
42− $ \s1 s2 -> property
43− $ runner3 s1 s2 testEther == ((s1, s2), (s1, map succ s2))
44− , testProperty "runner₁ == runner₂ == runner₃"
45− $ \s1 s2 -> property
46− $ same
47− [ runner1 s1 s2 testEther
48− , runner2 s1 s2 testEther
49− , runner3 s1 s2 testEther ]
50− ]
test/Regression/T10.hsdeleted−43
@@ -1,43 +0,0 @@
1−module Regression.T10 (test10) where
2−
3−import Control.Applicative
4−import Data.Functor.Identity
5−
6−import Ether
7−
8−import Test.Tasty
9−import Test.Tasty.QuickCheck
10−
11−testEther :: Integer -> StateT' Integer Maybe [Integer]
12−testEther m = range
13− where
14− range = liftA2 (:) yield (range <|> pure [])
15− yield = stateT' $ \n -> do
16− guard (n <= m)
17− Just (n, n + 1)
18−
19−testEther' :: Integer -> State' Integer [Integer]
20−testEther' m =
21− stateT' $ Identity . maybe ([], m + 1) id . runStateT' (testEther m)
22−
23−next1 :: Integer -> Integer -> Maybe Integer
24−next1 m n
25− | n <= m = Just (m + 1)
26− | otherwise = Nothing
27−
28−range1 :: Integer -> Integer -> Maybe [Integer]
29−range1 m n
30− | n <= m = Just [n..m]
31− | otherwise = Nothing
32−
33−test10 :: TestTree
34−test10 = testGroup "T10: Alternative instance"
35− [ testProperty "execStateT works"
36− $ \m n -> execStateT' (testEther m) n == next1 m n
37− , testProperty "evalStateT works"
38− $ \m n -> evalStateT' (testEther m) n == range1 m n
39− , testProperty "execState works"
40− $ \m n -> execState' (testEther' m) n == m + 1
41− , testProperty "evalState works"
42− $ \m n -> evalState' (testEther' m) n == [n..m]
43− ]
test/Regression/T11.hsdeleted−50
@@ -1,50 +0,0 @@
1−module Regression.T11 (test11) where
2−
3−import Ether
4−
5−import Data.Bool
6−import qualified Control.Monad.State as T
7−import qualified Control.Monad.Reader as T
8−
9−import Test.Tasty
10−import Test.Tasty.QuickCheck
11−
12−data STag
13−
14−testEther
15− :: ( MonadState STag [Integer] m
16− , T.MonadState Bool m
17− , T.MonadReader Integer m )
18− => m ()
19−testEther = do
20− T.modify not
21− f <- bool negate id <$> T.get
22− n <- T.ask
23− T.local succ testEther
24− modify @STag (f n:)
25−
26−model :: Integer -> [Integer]
27−model n = zipWith ($) (cycle [id, negate]) [n..]
28−
29−runner1 n
30− = flip (T.runReader) n
31− . flip (execLazyStateT @STag) []
32− . flip T.evalStateT False
33−
34−runner2 n
35− = flip T.evalState False
36− . flip (execLazyStateT @STag) []
37− . flip T.runReaderT n
38−
39−test11 :: TestTree
40−test11 = testGroup "T11: Lazy sequence"
41− [ testProperty "runner₁ works"
42− $ \l n -> property
43− $ take l (runner1 n testEther) == take l (model n)
44− , testProperty "runner₂ works"
45− $ \l n -> property
46− $ take l (runner2 n testEther) == take l (model n)
47− , testProperty "runner₁ == runner₂"
48− $ \l n -> property
49− $ take l (runner1 n testEther) == take l (runner2 n testEther)
50− ]
test/Regression/T12.hsdeleted−30
@@ -1,30 +0,0 @@
1−module Regression.T12 (test12) where
2−
3−import Ether
4−import Control.Lens
5−
6−import Test.Tasty
7−import Test.Tasty.QuickCheck
8−
9−data Foo
10−
11−succState :: Enum a => MonadState Foo a m => m ()
12−succState = modify @Foo succ
13−
14−testEther :: (Enum a, MonadState Foo (a, a) m) => m (a, a)
15−testEther = do
16− Ether.zoom @Foo _1 succState
17− Ether.zoom @Foo _2 $ modify @Foo pred
18− get @Foo
19−
20−model :: Enum a => (a, a) -> (a, a)
21−model (a1, a2) = (succ a1, pred a2)
22−
23−runner = evalState @Foo
24−
25−test12 :: TestTree
26−test12 = testGroup "T12: State zooming"
27− [ testProperty "runner works"
28− $ \(a1 :: Integer, a2 :: Integer) -> property
29− $ runner testEther (a1, a2) == model (a1, a2)
30− ]
test/Regression/T2.hsdeleted−28
@@ -1,28 +0,0 @@
1−module Regression.T2 (test2) where
2−
3−import Ether
4−
5−import Test.Tasty
6−import Test.Tasty.QuickCheck
7−
8−testEther :: (MonadReader' Integer m, MonadReader' Bool m) => m String
9−testEther = local' (succ :: Integer -> Integer) $ do
10− n :: Integer <- asks' (*2)
11− b <- local' not ask'
12− return (if b then "" else show n)
13−
14−runner1 (n :: Integer) = flip runReader' n . flip runReaderT' True
15−runner2 (n :: Integer) = flip runReader' True . flip runReaderT' n
16−
17−test2 :: TestTree
18−test2 = testGroup "T2: Implicit tags"
19− [ testProperty "runner₁ works"
20− $ \n -> property
21− $ runner1 n testEther == show (succ n * 2)
22− , testProperty "runner₂ works"
23− $ \n -> property
24− $ runner2 n testEther == show (succ n * 2)
25− , testProperty "runner₁ == runner₂"
26− $ \n -> property
27− $ runner1 n testEther == runner2 n testEther
28− ]
test/Regression/T3.hsdeleted−55
@@ -1,55 +0,0 @@
1−module Regression.T3 (test3) where
2−
3−import Ether
4−
5−import qualified Control.Monad.Reader as T
6−import qualified Control.Monad.State as T
7−
8−import Test.Tasty
9−import Test.Tasty.QuickCheck
10−
11−data RTag
12−data STag
13−
14−testMTL :: (T.MonadReader Int m, T.MonadState Int m) => m Int
15−testMTL = do
16− b <- T.get
17− a <- T.ask
18− T.put (a + b)
19− return (a * b)
20−
21−testEther
22− :: (MonadReader STag Int m, MonadState STag Int m, MonadReader RTag Int m)
23− => m (Int, Int, Int)
24−testEther = local @RTag (*2) $ do
25− a_mul_b <- tagAttach @STag testMTL
26− a_add_b <- get @STag
27− modify @STag negate
28− c <- ask @RTag
29− return (a_mul_b, a_add_b, c)
30−
31−runner1 s r
32− = flip (runReader @RTag) (negate r)
33− . flip (runReaderT @STag) r
34− . flip (runStateT @STag) s
35−runner2 s r
36− = flip (runReader @RTag) (negate r)
37− . flip (runStateT @STag) s
38− . flip (runReaderT @STag) r
39−
40−test3 :: TestTree
41−test3 = testGroup "T3: Tag attachement"
42− [ testProperty "runner₁ works"
43− $ \s r -> property
44− $ (==)
45− (runner1 s r testEther)
46− ((s * r, s + r, negate r * 2), negate (s + r))
47− , testProperty "runner₂ works"
48− $ \s r -> property
49− $ (==)
50− (runner2 s r testEther)
51− ((s * r, s + r, negate r * 2), negate (s + r))
52− , testProperty "runner₁ == runner₂"
53− $ \s r -> property
54− $ runner1 s r testEther == runner2 s r testEther
55− ]
test/Regression/T4.hsdeleted−24
@@ -1,24 +0,0 @@
1−module Regression.T4 (test4) where
2−
3−import Ether
4−
5−import Test.Tasty
6−import Test.Tasty.QuickCheck
7−
8−data RTag
9−
10−testEther :: MonadReader RTag Int m => m Int
11−testEther = ask @RTag
12−
13−runner r
14− = flip (runReader @RTag) (r' :: Int)
15− . flip (runReaderT @RTag) (r :: Int)
16− where
17− r' = negate r
18−
19−test4 :: TestTree
20−test4 = testGroup "T4: Nested same-tag readers"
21− [ testProperty "runner works"
22− $ \r -> property
23− $ runner r testEther == r
24− ]
test/Regression/T5.hsdeleted−42
@@ -1,42 +0,0 @@
1−module Regression.T5 (test5) where
2−
3−import Ether
4−
5−import Test.Tasty
6−import Test.Tasty.QuickCheck
7−
8−newtype Counter = Counter Int
9− deriving (Eq, Ord, Num, Enum)
10−
11−incCounter :: Counter -> Counter
12−incCounter = succ
13−
14−testEther
15− :: (Num a, Ord a)
16− => (MonadReader' a m, MonadState' Counter m)
17− => m a
18−testEther = do
19− a <- ask'
20− if a <= 0
21− then do
22− put' (0 :: Counter)
23− return 1
24− else do
25− modify' incCounter -- overriden in the base case
26− b <- runReaderT' testEther (a - 1)
27− modify' incCounter
28− return (a * b)
29−
30−runner :: (Num a, Ord a) => a -> (a, Counter)
31−runner a = runState' (runReaderT' testEther a) (0 :: Counter)
32−
33−factorial :: (Num a, Enum a) => a -> a
34−factorial a = product [1..a]
35−
36−test5 :: TestTree
37−test5 = testGroup "T5: Factorial via Ether"
38− [ testProperty "runner works"
39− $ \n -> property
40− $ let n' = fromIntegral n :: Integer
41− in runner n' == (factorial n', max 0 (Counter n))
42− ]
test/Regression/T6.hsdeleted−64
@@ -1,64 +0,0 @@
1−module Regression.T6 (test6) where
2−
3−import Data.Function
4−import Ether
5−
6−import Test.Tasty
7−import Test.Tasty.QuickCheck
8−
9−data DivideByZero = DivideByZero
10− deriving (Show)
11−
12−data NegativeLog a = NegativeLog a
13− deriving (Show)
14−
15−testEther
16− :: (Floating a, Ord a)
17− => (MonadExcept' DivideByZero m, MonadExcept' (NegativeLog a) m)
18− => a -> a -> m a
19−testEther a b = do
20− when (b == 0) (throw' DivideByZero)
21− let d = a / b
22− when (d < 0) (throw' (NegativeLog d))
23− return (log d)
24−
25−handleNegativeLog (NegativeLog (x :: Double)) = "nl: " ++ show x
26−handleDivideByZero DivideByZero = "dz"
27−
28−handleT' :: Functor m => (e -> a) -> ExceptT' e m a -> m a
29−handleT' h m = fmap (either h id) (runExceptT' m)
30−
31−runner1 :: Double -> Double -> String
32−runner1 a b = do
33− (show `fmap` testEther a b)
34− & handleT' handleNegativeLog
35− & handleT' handleDivideByZero
36− & runIdentity
37−
38−runner2 :: Double -> Double -> String
39−runner2 a b = do
40− (show `fmap` testEther a b)
41− & handleT' handleDivideByZero
42− & handleT' handleNegativeLog
43− & runIdentity
44−
45−logDiv :: Double -> Double -> String
46−logDiv a b
47− | b == 0 = "dz"
48− | d < 0 = "nl: " ++ show d
49− | otherwise = show (log d)
50− where
51− d = a / b
52−
53−test6 :: TestTree
54−test6 = testGroup "T6: Checked exceptions"
55− [ testProperty "runner₁ works"
56− $ \a b -> property
57− $ runner1 a b == logDiv a b
58− , testProperty "runner₂ works"
59− $ \a b -> property
60− $ runner2 a b == logDiv a b
61− , testProperty "runner₁ == runner₂"
62− $ \a b -> property
63− $ runner1 a b == runner2 a b
64− ]
test/Regression/T7.hsdeleted−51
@@ -1,51 +0,0 @@
1−module Regression.T7 (test7) where
2−
3−import Data.Monoid
4−import Control.Monad
5−
6−import Ether
7−import qualified Control.Monad.Writer as T
8−
9−import Test.Tasty
10−import Test.Tasty.QuickCheck
11−
12−data WTag
13−
14−testEther
15− :: Num a
16− => T.MonadWriter (Sum a) m
17− => MonadWriter WTag (Sum a) m
18− => [a] -> m ()
19−testEther xs = do
20− forM_ xs $ \x -> do
21− u1 <- T.tell (Sum x)
22− u2 <- tell @WTag (Sum 1)
23− when (u1 /= u2) $ error "Impossible"
24−
25−runner1 :: Num a => [a] -> (a, a)
26−runner1 xs =
27− let (s, c) = T.runWriter . execWriterT @WTag $ testEther xs
28− in (getSum s, getSum c)
29−
30−runner2 :: Num a => [a] -> (a, a)
31−runner2 xs =
32− let (c, s) = runWriter @WTag . T.execWriterT $ testEther xs
33− in (getSum s, getSum c)
34−
35−triangular :: Integral a => a -> a
36−triangular n = div (n * (n + 1)) 2
37−
38−test7 :: TestTree
39−test7 = testGroup "T7: Triangular via Ether"
40− [ testProperty "runner₁ works"
41− $ \n -> property
42− $ let n' = abs n :: Integer
43− in runner1 [1..n'] == (n', triangular n')
44− , testProperty "runner₂ works"
45− $ \n -> property
46− $ let n' = abs n :: Integer
47− in runner2 [1..n'] == (n', triangular n')
48− , testProperty "runner₁ == runner₂"
49− $ \(ns :: [Integer]) -> property
50− $ runner1 ns == runner2 ns
51− ]
test/Regression/T8.hsdeleted−51
@@ -1,51 +0,0 @@
1−module Regression.T8 (test8) where
2−
3−import Ether
4−
5−import qualified Control.Monad.State as T
6−
7−import Test.Tasty
8−import Test.Tasty.QuickCheck
9−
10−data Foo
11−data Bar
12−
13−testMTL1 :: T.MonadState Int m => m ()
14−testMTL1 = T.modify negate
15−
16−testMTL2 :: T.MonadState Bool m => m ()
17−testMTL2 = T.modify not
18−
19−testEther
20− :: (MonadState Foo Int m, MonadState Bar Bool m)
21− => m String
22−testEther = do
23− tagAttach @Foo testMTL1
24− tagAttach @Bar testMTL2
25− a <- gets @Foo show
26− b <- gets @Bar show
27− return (a ++ b)
28−
29−model :: Int -> Bool -> String
30−model a b = show (negate a) ++ show (not b)
31−
32−runner1 a b
33− = flip (evalState @Foo) a
34− . flip (evalStateT @Bar) b
35−
36−runner2 a b
37− = flip (evalState @Bar) b
38− . flip (evalStateT @Foo) a
39−
40−test8 :: TestTree
41−test8 = testGroup "T8: Multiple tag attachements"
42− [ testProperty "runner₁ works"
43− $ \a b -> property
44− $ runner1 a b testEther == model a b
45− , testProperty "runner₂ works"
46− $ \a b -> property
47− $ runner2 a b testEther == model a b
48− , testProperty "runner₁ == runner₂"
49− $ \a b -> property
50− $ runner1 a b testEther == runner2 a b testEther
51− ]
test/Regression/T9.hsdeleted−49
@@ -1,49 +0,0 @@
1−module Regression.T9 (test9) where
2−
3−import Ether
4−
5−import Test.Tasty
6−import Test.Tasty.QuickCheck
7−
8−data Foo
9−data Bar
10−
11−testEther1 :: MonadState Foo Int m => m String
12−testEther1 = do
13− modify @Foo negate
14− gets @Foo show
15−
16−testEther2 :: MonadState Bar Int m => m String
17−testEther2 = tagReplace @Foo @Bar testEther1
18−
19−testEther
20− :: (MonadState Foo Int m, MonadState Bar Int m)
21− => m String
22−testEther = do
23− a <- testEther1
24− b <- testEther2
25− return (a ++ b)
26−
27−model :: Int -> Int -> String
28−model a b = show (negate a) ++ show (negate b)
29−
30−runner1 a b
31− = flip (evalState @Foo) a
32− . flip (evalStateT @Bar) b
33−
34−runner2 a b
35− = flip (evalState @Bar) b
36− . flip (evalStateT @Foo) a
37−
38−test9 :: TestTree
39−test9 = testGroup "T9: Tag replacement"
40− [ testProperty "runner₁ works"
41− $ \a b -> property
42− $ runner1 a b testEther == model a b
43− , testProperty "runner₂ works"
44− $ \a b -> property
45− $ runner2 a b testEther == model a b
46− , testProperty "runner₁ == runner₂"
47− $ \a b -> property
48− $ runner1 a b testEther == runner2 a b testEther
49− ]
test/TupleInstances.hsdeleted−9
@@ -1,9 +0,0 @@
1−{-# OPTIONS -fno-warn-orphans #-}
2−{-# LANGUAGE CPP #-}
3−
4−module TupleInstances () where
5−
6−#ifdef DISABLE_TUP_INSTANCES
7−import Ether.Internal (makeTupleInstancesHasLens)
8−makeTupleInstancesHasLens [2]
9−#endif