Tying the Knot with a State monad

后端 未结 5 1888
隐瞒了意图╮
隐瞒了意图╮ 2021-01-30 16:42

I\'m working on a Haskell project that involves tying a big knot: I\'m parsing a serialized representation of a graph, where each node is at some offset into the file, and may r

5条回答
  •  日久生厌
    2021-01-30 17:20

    Regarding the implementation, I would make it a composition of a Reader monad (for the future) and a State monad (for past/present). The reason is that you set your future only once (in tie) and then don't change it.

    {-# LANGUAGE DoRec, GeneralizedNewtypeDeriving #-}
    
    import Control.Monad.State
    import Control.Monad.Reader
    import Control.Applicative
    
    newtype RecStateT s m a = RecStateT (StateT s (ReaderT s m) a) deriving
      ( Alternative
      , Applicative
      , Functor
      , Monad
      , MonadPlus
      )
    
    tie :: MonadFix m => RecStateT s m a -> s -> m (a, s)
    tie (RecStateT m) s = do
      rec (a, s') <- flip runReaderT s' $ flip runStateT s m
      return (a, s')
    
    getPast :: Monad m => RecStateT s m s
    getPast = RecStateT get
    
    getFuture :: Monad m => RecStateT s m s
    getFuture = RecStateT ask
    
    putPresent :: Monad m => s -> RecStateT s m ()
    putPresent = RecStateT . put
    

    Regarding your second question, it'd help to know your dataflow (i.e. to have a minimal example of your code). It's not true that strict patterns always lead to loops. It's true that you need to be careful so as not to create a non-producing loop, but the exact restrictions depend on what and how you're building.

提交回复
热议问题