haskellmonads# How can I use `liftIO` with State to print values inside that Monad?

I am trying to print inside the `State`

monad by using `liftIO`

function from `MonadIO`

class:

```
import Control.Monad.State
import Control.Monad.IO.Class
import Control.Applicative
facHelper :: Integer -> State Integer ()
facHelper 0 = pure ()
facHelper n = do
currentState <- get
liftIO $ putStrLn $ "n = " ++ show currentState
modify (*n)
facHelper (n-1)
factorial :: Integer -> Integer
factorial n = snd (runState (facHelper n) 1)
main :: IO ()
main = print $ factorial 6
```

However, I get the error:

No instance for (MonadIO Data.Functor.Identity.Identity) arising from a use of ‘liftIO’

If I look up `MonadIO`

class:

I see an instance:

```
MonadIO m => MonadIO (StateT s m)
```

And also see that `State s`

is a type alias

```
type State s = StateT s Identity
```

So, in principle, I could use `liftIO`

with `State`

. Where is the problem ?

Solution

If you want to do `IO`

, then `IO`

has to be at the bottom of your monad transformer stack. Here's the usual `mtl`

-way of fixing things:

```
facHelper :: (MonadIO m, MonadState Integer m) => Integer -> m ()
-- same definition as before
factorial :: Integer -> IO Integer
factorial n = execStateT (facHelper n) 1
main :: IO ()
main = factorial 6 >>= print
```

This uses `StateT Integer IO`

instead of `State Integer`

(i.e. `StateT Integer Identity`

).

If you're curious about the mechanical details of what went wrong with your approach:

- want
`MonadIO (State s)`

- have
`type State s = StateT s Identity`

, therefore want`MonadIO (StateT s Identity)`

- have
`MonadIO m => MonadIO (StateT s m)`

, and more specifically have`MonadIO Identity => MonadIO (StateT s Identity)`

, therefore want`MonadIO Identity`

- don't (and can't sensibly) have
`MonadIO Identity`

- Comparing lists in Haskell
- Is there a non-identity monad morphism M ~> M that is monadically natural in M?
- Problem with loading module ‘Distribution.Simple’
- Improving efficiency in Stirling numbers calculation
- Does sequencing an infinite list of IO actions by definition result in a never-ending action? Or is there a way to bail out?
- How to call pgQuery from postgresql-query?
- How to avoid whitespace after a tag (link) in Hamlet templates?
- Understanding type-directed resolution in Haskell with existential types
- Why is seq bad?
- Understanding bind function in Haskell
- How to create route that will trigger on any path in Servant?
- How do I use a global state in WAI middleware?
- nixos 23.11 cabal install mysql-simple problem - "Missing (or bad) C libraries"
- Is there a way to kill all forked threads in a GHCi session without restarting it?
- Why can an invalid list expression such as 2:1 be assigned to a variable, but not printed?
- Iterate over a type level list and call a function based on each type in the list
- How does this solution of Project Euler Problem 27 in the Haskell Wiki work?
- Why `Monad` is required to use `pure`?
- Can't do partial function definitions in GHCi
- recommended way to convert Double -> Float in Haskell
- Haskell profiling understanding cost centre summary for anonymous lambda
- Why is Haskell fully declarative?
- GHC Generating Redundant Core Operations
- Question about Event firing in reflex-frp
- Using Haskell's "Maybe", type declarations
- How can I elegantly invert a Map's keys and values?
- Why there is no output for wrapped IO in Haskell?
- What are the definitions of Weather and Memory in xmobar repo?
- Serializing a Data.Text value to a ByteString without unnecessary \NUL bytes
- Using Haskell with VS Code