Giter VIP home page Giter VIP logo

Comments (9)

HeinrichApfelmus avatar HeinrichApfelmus commented on June 25, 2024

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.

andrewthad avatar andrewthad commented on June 25, 2024

@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.

HeinrichApfelmus avatar HeinrichApfelmus commented on June 25, 2024

@andrewthad

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.

andrewthad avatar andrewthad commented on June 25, 2024

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.

emilaxelsson avatar emilaxelsson commented on June 25, 2024

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.

andrewthad avatar andrewthad commented on June 25, 2024

@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.

HeinrichApfelmus avatar HeinrichApfelmus commented on June 25, 2024

@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.

emilaxelsson avatar emilaxelsson commented on June 25, 2024

Ah, yes indeed! (It wasn't quite the identity function because of the call to local on k, but still wrong.)

from operational.

 avatar commented on June 25, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.