State monad: how to "print" an intermediate value in Haskell

I am new to haskell and I have the 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 the state after put (n+1)

and continue with calculations like this

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

      

How would the whole code look like this?

+3


source to share


2 answers


If you want to trigger I / O as part of a state computation, you can change the type tick

to return StateT Int IO Int

and use liftIO

. Then you can start it with execStateT

:



import Control.Monad.State.Lazy
import Control.Monad.IO.Class (liftIO)

tick :: StateT Int IO Int
tick = do n <- get
          put (n+1)
          liftIO $ print (n+1)
          return n

plusOne :: Int -> IO Int
plusOne = execStateT tick

main = plusOne 1 >> pure ()

      

+5


source


Another option, since you would need to use IO

anyway to print the value in the intermediate state, would be to use IORef

. It is a container that has an updatable 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

      



Then you can 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

      

0


source







All Articles