首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用IORef与镜片?

如何使用IORef与镜片?
EN

Stack Overflow用户
提问于 2014-08-21 10:18:07
回答 2查看 605关注 0票数 5

想知道如何最好地将Control.Lens包与IORef组合起来。具体来说,我希望能够使用atomicModifyIORef和透镜,这样我就可以提供a -> (a, b)类型的函数,并从操作中返回一个值。代码片段:

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-08-21 13:17:02

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

注意,Lens类型被定义为

代码语言:javascript
复制
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t

事实证明,如果让f成为(,) a Functor,这几乎完全符合您希望使用的转换inc的类型,只不过您确实希望a成为元组的最后一个元素,而不是第一个。修复之后,下面是我最后得到的结果:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2014-08-21 18:33:57

我发现定义一个使用IORefes操作Lens的助手函数是很方便的。正如rjan Johansen所提到的,atomicModifyIORef使用与Functor实例(,)不同的对顺序,因此我们需要交换。由于您希望具有a -> (a, b)类型的函数,所以我们也需要交换这个函数。

代码语言:javascript
复制
{-# 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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25423793

复制
相关文章

相似问题

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