Closed nhenin closed 4 years ago
{-# language RankNTypes, ScopedTypeVariables, QuantifiedConstraints, GADTs #-}
module Dolla.Adapter.Pipes.State (glom) where
import qualified Control.Lens as L
import qualified Control.Lens.Zoom as LZ
import Control.Monad.Morph
-- | Work smaller.
--
-- @
-- glom :: Monad m => L.Lens' s' s -> Pipe x y (StateT s m) a -> Pipe x y (StateT s' m) a -- @
glom :: (MFunctor t, L.Zoom m m' s s', forall x. Functor (q x), q ~ LZ.Zoomed m)
=> L.ALens' s' s
-> t m a
-> t m' a
glom al = hoist $ L.zoom (L.cloneLens al)
We are doing it using this...
@nhenin: I think you are on the right track by using zoom
as in your latter example.
To simplify this a little bit, let's assume that I want to combine two Pipe
s with different underlying StateT
types, like these two:
pipe0 :: Pipe a b (StateT s0 m) r
pipe1 :: Pipe b c (StateT s1 m) r
What I would do is to transform both of them to agree on the same composite state type so that the result has type:
result :: Pipe a c (StateT (s0, s1) m) r
Note that the composite state type does not need to be a tuple (it could be a record, for example), but I'll use a tuple for simplicity.
The way I would implement that is:
import Control.Monad.Trans.State (StateT)
import Pipes (Pipe, hoist, (>->))
import Control.Lens (zoom, _1, _2)
example
:: Monad m
=> Pipe a b (StateT s0 m) r
-> Pipe b c (StateT s1 m) r
-> Pipe a c (StateT (s0, s1) m) r
example p0 p1 = hoist (zoom _1) p0 >-> hoist (zoom _2) p1
The idea is to do something like this :
I would say nesting a sub-stream somehow... I have difficulties to implement this with
Pipes
Here a simple example that explain what I'm trying to do... :