State monad: How to `print` intermediate value in Haskell

Viewed 916

I'm new in haskell and I have following code

module StateTest where

import Control.Monad.State.Lazy

tick :: State Int Int
tick = do n <- get
          put (n+1)
          return n

plusOne :: Int -> Int
plusOne = execState tick

main = print $ plusOne 1

And I want to print state value after put (n+1) and continue computation like this

tick = do n <- get
          put (n+1)
          print
          return n

How whole code will look following to this?

2 Answers

Another option, since you would have to use IO anyway to print a value in the intermediate state, would be to use IORef. It's a container that has an updateable value.

module Main where

import Data.IORef

tick :: IORef Int -> IO (IORef Int)
tick ref = do
  modifyIORef' ref (+1)
  -- you can also print here since it is IO
  pure ref

main :: IO ()
main = do
  counter <- newIORef 0

  tick counter
  v2 <- readIORef counter
  print v2

  tick counter
  v2 <- readIORef counter
  print v2

You can then clean it up with ReaderT.

module Main where

import Data.IORef
import Control.Monad.Reader

readerTick :: ReaderT (IORef Int) IO ()
readerTick = do
  ref <- ask
  -- can also print here with liftIO $ print ...
  liftIO $ modifyIORef' ref (+1)

main :: IO ()
main = do
  counter <- newIORef 0

  runReaderT readerTick counter
  v1 <- readIORef counter
  print v1

  runReaderT readerTick counter
  v2 <- readIORef counter
  print v2
Related