Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zooming in MonadState #316

Closed
nikita-volkov opened this issue Jul 9, 2013 · 4 comments
Closed

Zooming in MonadState #316

nikita-volkov opened this issue Jul 9, 2013 · 4 comments

Comments

@nikita-volkov
Copy link

I have a function in which I'm trying to use zoom like so:

replaceArtistCascadingly 
  :: Artist -> Artist -> Acid.Update ProcessedCatalogue ()
replaceArtistCascadingly old new = do
  zoom albumsL $ do
    undefined

Acid.Update is an instance of MonadState. However I get the following error:

  No instance for (Functor
                       (Control.Lens.Internal.Zoom.Zoomed
                          (Acid.Update ProcessedCatalogue) [Album]))
      arising from a use of `albumsL'

But if I change the type signature to

Artist -> Artist -> State ProcessedCatalogue ()

the function compiles just fine.

@glguy
Copy link
Collaborator

glguy commented Jul 9, 2013

You need to provide the 'type instance' for 'Zoomed (Acid.Update s)' and not just a MonadState instance

@ekmett
Copy link
Owner

ekmett commented Jul 12, 2013

zoom can't (currently) work polymorphically over MonadState. MonadState isn't sufficient for us to be able to swap out the type of state in your monad.

As a somewhat idle aside before I forget:

One option to make this less painful for users is we could make a monad transformer to the supplied monad that switches out the state for the nested context rather than swapping the state type. However, that has a consequence. Right now the correctness of applying zoom to a Traversal hinges on the fact that it can't write to other parts of the state than what is zoomed. That would be lost by the transformer version.

@ghost ghost assigned ekmett Jul 12, 2013
@ekmett ekmett closed this as completed Jul 12, 2013
@neongreen
Copy link
Contributor

@ekmett What do you mean by “MonadState isn't sufficient for us to be able to swap out the type of state in your monad”? I thought it meant that you can change the type of the state, but it looks like you can't:

> flip execState (1 :: Int, 2) $ zoom _1 $ id %= show

<interactive>:4:45:
    Couldn't match type Int with [Char]
    arising from a functional dependency between:
      constraint MonadState String (StateT Int Identity)
        arising from a use of ‘%=’
      instance MonadState s (StateT s m) at <no location info>
    In the second argument of ($), namely id %= show
    In the second argument of ($), namely zoom _1 $ id %= show
    In the expression:
      flip execState (1 :: Int, 2) $ zoom _1 $ id %= show

Or did you just mean that with MonadState we'd only be able to use lenses of the type Lens' s s?

@neongreen
Copy link
Contributor

On further reflection, yeah, of course it's impossible. Nevermind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants