(x `div` y)*y + (x `mod` y) == xWARNING: This function is partial (because it throws when 0 is passed as the divisor) for all the integer types in base.
Main> :t modify ((+1) :: Int -> Int) modify (...) :: (MonadState Int a) => a ()This says that modify (+1) acts over any Monad that is a member of the MonadState class, with an Int state.
data DatabaseError = ... performDatabaseQuery :: (MonadError DatabaseError m, ...) => m PersistedValue data AppError = MkDatabaseError DatabaseError | ... app :: (MonadError AppError m, ...) => m ()Given these types, performDatabaseQuery cannot be used directly inside app, because the error types don't match. Using modifyError, an equivalent function with a different error type can be constructed:
performDatabaseQuery' :: (MonadError AppError m, ...) => m PersistedValue performDatabaseQuery' = modifyError MkDatabaseError performDatabaseQuerySince the error types do match, performDatabaseQuery' _can_ be used in app, assuming all other constraints carry over. This works by instantiating the m in the type of performDatabaseQuery to ExceptT DatabaseError m', which satisfies the MonadError DatabaseError constraint. Immediately, the ExceptT DatabaseError layer is unwrapped, producing Either a DatabaseError or a PersistedValue. If it's the former, the error is wrapped in MkDatabaseError and re-thrown in the inner monad, otherwise the result value is returned.
ref <- newIORef 0 replicateM_ 1000000 $ modifyIORef ref (+1) readIORef ref >>= printTo avoid this problem, use modifyIORef' instead.
>>> :{ runST (do ref <- newSTRef "" modifySTRef ref (const "world") modifySTRef ref (++ "!") modifySTRef ref ("Hello, " ++) readSTRef ref ) :} "Hello, world!"Be warned that modifySTRef does not apply the function strictly. This means if the program calls modifySTRef many times, but seldom uses the value, thunks will pile up in memory resulting in a space leak. This is a common mistake made when using an STRef as a counter. For example, the following will leak memory and may produce a stack overflow:
>>> import Control.Monad (replicateM_) >>> :{ print (runST (do ref <- newSTRef 0 replicateM_ 1000 $ modifySTRef ref (+1) readSTRef ref )) :} 1000To avoid this problem, use modifySTRef' instead.
ref <- newIORef '1' forever $ atomicModifyIORef ref (\_ -> ('2', ()))Use atomicModifyIORef' or atomicWriteIORef to avoid this problem. This function imposes a memory barrier, preventing reordering; see Data.IORef#memmodel for details.
atomicModifyIORef' ref (x -> (x+1, undefined))will increment the IORef and then throw an exception in the calling thread. This function imposes a memory barrier, preventing reordering; see Data.IORef#memmodel for details.