First, sorry if that title makes no sense. I am a little out of my depth here with the terminology.So, imagine that I'm writing a text editor in Haskell. For the purposes of this question, let's consider a toy text editor that only operates on a single line of text, and has three primitive operations:Insert a character at the cursor (so all characters under and to the right of the cursor, if any, are moved to the right).Move the cursor to the left (no effect if it's already at position zero)Move the cursor to the right (no effect if it's already at the end of the line)Obviously I am dealing with a state (the buffer of my text editor, and the position of its cursor) and some operations that can be applied in some sequence to modify the state. So, I'm going to implement this thing using a state monad that holds two lists, one for the characters behind the cursor and another for those after it. I will write three simple functions in the state monad to provide my three primitive operations:data ListState a = ListState {                     before :: [a],                     after :: [a]                   }insert :: MonadState (ListState a) m => a -> m ()insert x = do  ListState bs as <- get  put $ ListState bs (x:as)moveForward :: MonadState (ListState a) m => m ()moveForward = do  ListState bs as <- get  case as of    (a:as') -> put $ ListState (a:bs) as'    _       -> return ()moveBackward :: MonadState (ListState a) m => m ()moveBackward = do  ListState bs as <- get  case bs of    (b:bs') -> put $ ListState bs' (b:as)    _       -> return ()Cool! Now I can use these three primitives to do more complicated things:insertList :: MonadState (ListState a) m => [a] -> m ()insertList xs = forM_ (reverse xs) insertfoo :: MonadState (ListState Char) m => m ()foo = do  insertList This is a idea!  replicateM_ 10 moveForward  insertList bad   replicateM_ 3 moveBackward  insertList n'tmain = let state = ListState             state' = execState foo state       in  putStrLn $ reverse (before state') ++ after state'Using my primitive DSL, I've defined a function using repeated calls to insert to insert a whole list at once, and another function foo that combines all these functions to circuitously build a string:(mdunsmuir@altair) mdunsmuir/projects >> ./ToyDSL This isn't a bad idea!I find myself following this pattern a lot: define some data type to hold a state that I want to apply a sequence of operations to, and then build out a DSL starting with the most basic atomic operations and with more complex operations defined as combinations of those primitives.My question is pretty open-ended: For this sort of problem (imagine a more realistic text editor implemented in the same way), is this a generally valid approach? What other approaches might one use? The primary thing that I find concerning about this approach is that if you don't take a disciplined approach to the design of your DSL, you can run into a lot of unpleasant issues that I associate with imperative programming.
Is the use of DSLs in a state monad a good approach to building complex stateful computations?
design patterns;functional programming;haskell
Although this can be a good idea at one level, you want to avoid passing monads around all over the place if you can.  It's easier to read, write, compose, and reuse if you write your functions normally, then modify them into a monadic context as needed:insert x (Buffer before after) = Buffer (x:before) afterinsertList xs (Buffer before after) = Buffer (reverse xs ++ before) aftermoveForward (Buffer before (x:after)) = Buffer (x:before) aftermoveBackward (Buffer (x:before) after) = Buffer before (x:after)modify2 f a = do {x <- get; put (f a x) } insertM = modify2 insertinsertListM = modify2 insertListmoveForwardM = modify moveForwardmoveBackwardM = modify moveBackward