Comments (9)
Actually, it should always be possible to write the necessary instances using the viewT
function. This is the appropriate destructor for ProgramT
. The MonadReader
instance in the source code uses the constructors only because it is convenient, not because it is necessary.
I'm not familiar with Control.Lens.Zoom. Could you elaborate on the particular class that you want to implement?
from operational.
@HeinrichApfelmus I just spent a while trying to write local
(from MonadReader
) using viewT
instead of pattern matching, and it doesn't seem possible to me. Can you show me how this can be done? Because if it is possible, then the Zoom
instance is certainly doable as well. I just can't see what the technique for doing this is.
from operational.
I do not test the code below, but I believe this should do the trick:
EDIT: Updated this version to work correctly. See below for a shorter variant.
{-# LANGAUAGE RankNTypes, ScopedTypeVariables #-}
import Control.Monad
import Control.Monad.Operational
import Control.Monad.Trans
instance MonadReader r m => MonadReader r (ProgramT instr m) where
ask = lift ask
local = liftLocal local
liftLocal :: forall m instr b r. Monad m => (forall a. r -> m a -> m a)
-> (r -> ProgramT instr m b -> ProgramT instr m b)
liftLocal local r m = eval =<< lift (local r (viewT m))
where
eval :: Monad m => ProgramViewT instr m c -> ProgramT instr m c
eval (Return x) = return x
eval (instr :>>= k) = singleton instr >>= liftLocal local r . k
It's really just another way of writing the code that used constructors. Note that the return type of viewT
being in the Monad m
corresponds to the case where we handle the Lift
constructor.
from operational.
I've created a branch that attempts to use the alternative MonadReader
instance you have provided: andrewthad@80f23e9
It fails to compile with the following error:
/home/andrew/Development/operational/src/Control/Monad/Operational.hs:315:32:
Couldn't match type ‘m’ with ‘ProgramT instr m’
‘m’ is a rigid type variable bound by
the type signature for
liftLocal :: Monad m =>
(forall a. r -> m a -> m a)
-> r -> ProgramT instr m b -> ProgramT instr m b
at src/Control/Monad/Operational.hs:313:21
Expected type: ProgramT instr m (ProgramViewT instr m b)
Actual type: m (ProgramViewT instr m b)
I don't think that this issue can be worked around. The problem is that viewT
wraps the result in the the ProgramT
's inner monad m
, and you can't get rid of the m
. My issue about mapProgramT
illustrates a similar situation in which a function that modifies a ProgramT
cannot be written without access to the data constructors.
from operational.
This works for me:
local r p = do
v <- lift $ viewT p
case v of
Return a -> return a
i :>>= k -> singleton i >>= local r . k
from operational.
@emilaxelsson You are right. Thanks for coming up with the solution.
I guess the only remaining question is how the runtime efficiency of the two approaches differs. I don't know how a pattern match with viewT
compares to a real pattern match on a program. I'll try to benchmark these two approaches as some point to see if viewT
incurs a considerable slowdown or not. If it does, then it seems like exporting the data constructors would be helpful for people who want to really optimize a certain function.
from operational.
@emilaxelsson Thanks! Note that this should actually be
local r p = do
v <- lift $ local r (viewT p)
case v of
Return a -> return a
i :>>= k -> singleton i >>= local r . k
You need to include a call to local
for the base monad, otherwise the function will just be the identity function.
from operational.
Ah, yes indeed! (It wasn't quite the identity function because of the call to local
on k
, but still wrong.)
from operational.
I'm now very skeptical that you can even do this directly, with or without the constructor, so I'm just going to close the issue based on the discussion.
from operational.
Related Issues (17)
- MonadProgram typeclass for nicer transformer stacks HOT 2
- helper function interpretWithMonadT HOT 4
- mapProgramT HOT 2
- Pattern Synonyms for `Return` and `:>>=` HOT 7
- ProgramT and ProgramViewT are not really GADTs HOT 1
- Package documentation not as approachable as it maybe could be HOT 5
- Issues with `.cabal` file HOT 2
- Add interpretWithMonadT HOT 1
- Does not build with stackage nightly-2021-06-21 (ghc-9.0.1) HOT 1
- Hackage release with 9.0.1 support HOT 3
- PoorMansConcurrency Example doesn't compile HOT 2
- 0.2.4.0 fails to build with GHC-7.8 and older HOT 3
- Compatibility with mtl-2.3 HOT 2
- Add evalRandTIO HOT 3
- Broken links in documentation HOT 1
- MonadTransControl or MonadBaseControl instances HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from operational.