module Foo (go) where import Control.Monad.Writer.Strict import Data.Monoid (Sum(..)) type Reg = Double data S1 = S1 data S2 = S2 Double addReg :: Double -> Writer (Sum Reg) () addReg = tell . Sum f :: S1 -> Double -> Writer (Sum Reg) (S1,Double) f S1 i = do addReg $ max 0.1 i pure (S1,i) g :: S2 -> Double -> Writer (Sum Reg) (S2,Double) g (S2 x) i = do addReg $ max x i pure (S2 (x+i),sin (x/i)) go :: (((S1, S2), Double), Reg) go = fmap getSum $ runWriter $ do let i = 1 :: Double let (s1,s2) = (S1,S2 0) (s1',o1) <- f s1 i (s2',o2) <- g s2 (min o1 i) pure ((s1',s2'),o2)