Closed goertzenator closed 2 years ago
Yeah, it's in fact trivial.
stateToStateViaLens :: Member (State bigSt) r
=> Lens' bigSt smallSt
-> Sem (State smallSt ': r) a
-> Sem r a
stateToStateViaLens lens = interpret $ \case
Put smallSt -> modify' (set lens smallSt)
Get -> gets (view lens)
I think this would be a good addition. I do not want to depend on lens
, but that's what microlens
is for. I'd welcome a pull request.
If you want combinators similar to the MonadState
ones in lens
, I'm significantly less sure about that. You'd have to convince me it's worth it.
Edit:
Or we could make it a separate library à la fused-effects
.
Thanks, but I'm struggling to understand how to apply that. Below is my [incorrect] guess, and the last function lensplay2
illustrates what I seek to achieve.
https://gist.github.com/goertzenator/2c055e96679c373a47cb894580725317
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fplugin=Polysemy.Plugin #-}
module Test where
import Data.Functor.Const
import Lens.Micro
import Polysemy
import Polysemy.State
view :: MemberWithError (State s) r => Getting a s a -> Sem r a
view l = getConst <$> gets (l Const)
(%=) :: MemberWithError (State s) r => ASetter s s a b -> (a -> b) -> Sem r ()
l %= f = modify (l %~ f)
(+=) :: (MemberWithError (State s) r, Num a) => ASetter s s a a -> a -> Sem r ()
l += x = l %= (+ x)
(*=) :: (MemberWithError (State s) r, Num a) => ASetter s s a a -> a -> Sem r ()
l *= x = l %= (* x)
test :: Member (State (Int, Int)) r => Sem r ()
test = do
_1 += 232
_2 *= 6
-- (233, 666)
runTest = run $ execState (1, 111) test
As a microlens user, I would prefer rewriting functions in microlens-mtl
with polysemy types, so that lenses can be used directly. Maybe we can make a library called microlens-polysemy
, though it seems to be trivial XD
Separate package sounds like a good idea - at least because we could then do the same thing e.g. for optics
:slightly_smiling_face:
I think it might be worth mentioning here that there's a library implementing something along these lines: https://hackage.haskell.org/package/polysemy-optics
Closing this; feel free to reopen if you feel it's still an issue.
The
lens
library cannot be used with the Polysemy State effect. Can this be enabled in some way?A few ideas can be found in this reddit thread.