
Simon, On Thu, 2013-10-03 at 08:07 +0000, Simon Peyton-Jones wrote:
If you are using the lens library yourself, could you spare a few minutes to tell me how you are using it?
I'm not a heavy 'lens'-user (yet), and this might not be the most pretty use-case from a theoretic point of view, but anyway: I use 'lens' in Kontiki [1], my implementation of Raft [2], a fairly recent consensus protocol for distributed systems (think Paxos & multi-Paxos, Zookeeper,...). The Raft protocol description is fairly imperative ("When in state S, if you receive a message M, broadcast message M'(M) to all other nodes, append entry E(M) to your log, and update the state to S'(S)"), so in order to keep the code close to this description, I created a TransitionT monad transformer (where the underlying monad should, in some cases, provide access to the persisted log of the system, most likely requiring IO access, but this is abstracted over), which is basically RWST. The R environment gives access to system configuration (e.g. the set of nodes (or at least their names/IDs) part of the cluster), W is used to output/list Commands to be executed as part of a state transition, S gives access to the current state, and a transition should yield a new state (or the old one if e.g. a message is received which should be ignored in the current state). See [3] for an overview of the types involved. Finally, after this long introduction, the 'lens' part: thanks to the 'lens' operators, and my types involved in the TransitionT monad (specifically the R environment and S state) being lens'ified, accessing R & S becomes fairly unobtrusive and more imperative-looking (which makes sense when using RWS). As an example, in [4], you see some parts of the current (Candidate) state being accessed: currentTerm <- use cCurrentTerm votes <- use cVotes Not using 'lens', this would be something (OTOH) like currentTerm <- fmap _cCurrentTerm get which is less familiar from an imperative POV. Then also updating the current state 'in-place' (not for real, obviously): cVotes %= Set.insert sender And accessing the configuration (R) environment, e.g.: nodeId <- view configNodeId See other handler functions in that module, or in the Follower and Leader modules in the same directory, for more examples. Regards, Nicolas [1] https://github.com/NicolasT/kontiki [2] https://ramcloud.stanford.edu/wiki/download/attachments/11370504/raft.pdf [3] https://github.com/NicolasT/kontiki/blob/master/src/Network/Kontiki/Types.hs [4] https://github.com/NicolasT/kontiki/blob/master/src/Network/Kontiki/Raft/Can...
participants (1)
-
Nicolas Trangez