Can I make a Lens with a Monad constraint?

后端 未结 3 672
挽巷
挽巷 2020-12-31 08:26

Context: This question is specifically in reference to Control.Lens (version 3.9.1 at the time of this writing)

I\'ve been using the le

3条回答
  •  感动是毒
    2020-12-31 09:12

    I had the same problem. I tried the methods in Petr and Cirdec's answers but never got to the point I wanted to. Started working on the problem, and at the end, I published the references library on hackage with a generalization of lenses.

    I followed the idea of the yall library to parameterize the references with monad types. As a result there is an mvar reference in Control.Reference.Predefined. It is an IO reference, so an access to the referenced value is done in an IO action.

    There are also other applications of this library, it is not restricted to IO. An additional feature is to add references (so adding _1 and _2 tuple accessors will give a both traversal, that accesses both fields). It can also be used to release resources after accessing them, so it can be used to manipulate files safely.

    The usage is like this:

    test = 
      do result <- newEmptyMVar
         terminator <- newEmptyMVar
         forkIO $ (result ^? mvar) >>= print >> (mvar .= ()) terminator >> return ()
         hello <- newMVar (Just "World")
         forkIO $ ((mvar & just & _tail & _tail) %~= ('_':) $ hello) >> return ()
         forkIO $ ((mvar & just & element 1) .= 'u' $ hello) >> return ()
         forkIO $ ((mvar & just) %~= ("Hello" ++) $ hello) >> return ()
    
         x <- runMaybeT $ hello ^? (mvar & just) 
         mvar .= x $ result
         terminator ^? mvar
    

    The operator & combines lenses, ^? is generalized to handle references of any monad, not just a referenced value that may not exist. The %~= operator is an update of a monadic reference with a pure function.

提交回复
热议问题