How to use IORef with lenses?

Think about the best way to combine Control.Lens with IORefs. In particular, I would like to be able to use atomicModifyIORefwith lenses so that I can provide a type function a -> (a, b)and return a value from an operation. Code snippet:

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
+4
source share
2 answers

, - %%~, 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, , a . , :

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
+6

IORef Lens es. , atomicModifyIORef , Functor (,), . a -> (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
+3

All Articles