首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ReaderT IORef的缩放实例

ReaderT IORef的缩放实例
EN

Stack Overflow用户
提问于 2018-02-10 11:46:50
回答 1查看 128关注 0票数 1

我是个镜头新手,在实现这个类型的Zoom实例时遇到了麻烦:

代码语言:javascript
复制
newtype MyStateT s m a = MyStateT
    { unMyStateT :: ReaderT (IORef s) m a
    } deriving (Functor, Applicative, Monad, MonadIO)

instance (MonadIO m) => MonadState s (MyStateT s m) where
    get = MyStateT $ ReaderT $ liftIO . readIORef
    put x = MyStateT $ ReaderT $ \ref -> liftIO $ writeIORef ref x

我一直在尝试创建一个带有镜头子状态的新IORef,在该子状态上运行ReaderT,然后获取更改后的子状态并在主IORef中替换它:

代码语言:javascript
复制
type instance Zoomed (MyStateT s m) = Focusing m
instance (Monad m) => Zoom (MyStateT s m) (MyStateT t m) s t where
    zoom l (MyStateT r) =
        MyStateT $ ReaderT $ \ref -> do
            s <- liftIO $ readIORef ref
            ref' <- liftIO $ newIORef $ s ^. l
            let v = runReader r ref'
            subS' <- liftIO $ readIORef ref'
            let s' = s & l .~ subS'
            liftIO $ writeIORef ref s'
            return v

l似乎与普通镜头不同,所以^..~无法使用它进行编译,我得到的错误如下:

代码语言:javascript
复制
    • Couldn't match type ‘Focusing m c t’ with ‘Const s t’
  Expected type: Getting s t s
    Actual type: LensLike' (Zoomed (MyStateT s m) c) t s
   • Couldn't match type ‘Focusing m c t’ with ‘Identity t’
  Expected type: ASetter t t s s
    Actual type: LensLike' (Zoomed (MyStateT s m) c) t s

有人能帮我让这个Zoom实例正常工作吗?谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-11 02:22:11

我的建议是:

代码语言:javascript
复制
type instance Zoomed (MyStateT s m) = Focusing m

instance (MonadIO m) => Zoom (MyStateT s m) (MyStateT t m) s t where
    zoom l (MyStateT r) =
        MyStateT $ ReaderT $ \ref -> do
            s <- liftIO $ readIORef ref
            (v', s') <- unfocusing . flip l s $ \t -> Focusing $ do
                ref' <- liftIO (newIORef t)
                v <- runReaderT r ref'
                t' <- liftIO (readIORef ref')
                return (v, t')
            liftIO $ writeIORef ref s'
            return v'
    {-# INLINE zoom #-}

您在使用(^.)(.~)时遇到的问题是,它们适用于Lens,而后者在函数器中是多态的。但是这里的函数器被固定为Zoomed (MyState s m) c,即Focusing m c。因此,您需要使用函数应用程序直接应用l

注意:您需要对此实现稍加小心。IORef不是原子的,除非您在纯函数上使用atomicModifyIORef (这在zoom中似乎是不可能的)。因此,将MVartakeMVarputMVar一起使用可能更有意义,以确保在多线程环境中运行时计算工作正常。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48717004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档