【问题标题】:How to use IORef with lenses?如何将 IORef 与镜头一起使用?
【发布时间】:2014-08-21 10:18:07
【问题描述】:

想知道如何最好地将Control.Lens 包与IORefs 结合起来。具体来说,我希望能够将atomicModifyIORef 与镜头一起使用,以便我可以提供a -> (a, b) 类型的函数并从操作中返回一个值。代码sn-p:

let inc x = (x+1, x)
ior <- newIORef ((1, 1) :: (Int, Int))
thisShouldBe1 <- ior & atomicModifyIORef ?? _1 inc -- this is the bit I'm stuck on

【问题讨论】:

    标签: haskell atomic haskell-lens ioref


    【解决方案1】:

    原则上,需要的镜头操作员实际上是%%~,这只是id 的方便同义词。但是,由于atomicModifyIORef(,) a Functor 中使用的元组排序存在令人讨厌的不兼容,它需要进行一些交换才能工作。我不认为生成的运算符是预定义的,但我在下面给它起了初步名称swappedId

    注意Lens 类型定义为

    type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
    

    事实证明,如果你让f 成为(,) a Functor,这几乎完全适合你想要用来转换你的inc 的类型,除了你真的想要@987654333 @ 成为元组的最后一个元素而不是第一个元素。解决这个问题后,我得到了以下结果:

    import Data.IORef
    import Control.Lens
    
    l `swappedId` f = f & mapping swapped %~ l
    
    main = do
        let inc x = (x+1, x)
        ior <- newIORef ((1, 1) :: (Int, Int))
        thisShouldBe1 <- atomicModifyIORef ior $ _1 `swappedId` inc
        print thisShouldBe1
        print =<< readIORef ior
    

    【讨论】:

      【解决方案2】:

      我发现定义一个辅助函数来使用Lenses 操作IORefs 很方便。正如 Ørjan Johansen 所提到的,atomicModifyIORef 使用与Functor 实例(,) 不同的配对顺序,因此我们需要交换。既然你想要a -&gt; (a, b)类型的函数,我们也需要交换这个函数。

      {-# LANGUAGE RankNTypes #-}
      import Control.Lens
      import Data.IORef
      import Data.Tuple (swap)
      
      -- | Atomically modifies an 'IORef' using a lens
      atomicModifyWithLens :: IORef a -> Lens a a b c -> (b -> (c, r)) -> IO r
      atomicModifyWithLens ref l f =
          atomicModifyIORef ref (swap . traverseOf l (swap . f))
      
      main = do
          let inc x = (x+1, x)
          ior <- newIORef ((1, 1) :: (Int, Int))
          thisShouldBe1 <- atomicModifyWithLens ior _1 inc
          print thisShouldBe1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-13
        • 2022-01-22
        • 1970-01-01
        • 2019-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多