# Using unsafePerformIO safely?

**URL:** <https://discourse.haskell.org/t/using-unsafeperformio-safely/4146>\
**Category:** Uncategorized\
**Created:** [February 28, 2022, 2:41pm UTC](https://discourse.haskell.org/t/using-unsafeperformio-safely/4146 "2022-02-28T14:41:23Z")\
**Posts on this page:** 1\
**Showing post:** 39

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [March 9, 2022, 4:49pm UTC](https://discourse.haskell.org/t/using-unsafeperformio-safely/4146/39 "2022-03-09T16:49:45Z")

</div>

> [@sgraf](#):
>
> I think [the documentation of `unsafePerformIO`](https://hackage.haskell.org/package/base-4.16.0.0/docs/System-IO-Unsafe.html#v:unsafePerformIO) is clear enough to answer this, specifically:
> 
> > For this to be safe, the `IO` computation should be free of side effects and independent of its environment.

From page 17 of 51 in Launchbury and Peyton-Jone’s [State in Haskell](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.52.3656&rep=rep1&type=pdf):

```haskell
dfs g vs = runST (
              newArr (bounds g) False `thenST` \ marks ->
              search marks vs
           )
  where search :: MutArr s Vertex Bool -> [Vertex]
                  -> ST s [Tree Vertex]
        search marks [] = returnST []
        search marks (v:vs) = readArr marks v `thenST` \ visited ->
                              if visited then
                                 search marks vs
                              else
                                writeArr marks v True `thenST_`
                                search marks (g!v) `thenST` \ ts ->
                                search marks vs `thenST` \ us ->
                                returnST ((Node v ts): us)

```

where:

```haskell
type Graph = Array Vertex [Vertex]
data Tree a = Node a [Tree a]

```

Here’s one way to rewrite that original code for `dfs`:

```haskell
dfs g vs = unsafePerformIO (
              newIOArray (bounds g) False >>= \ marks ->
              search marks vs
           )
  where search :: IOArray Vertex Bool -> [Vertex]
                  -> IO [Tree Vertex]
        search marks [] = return []
        search marks (v:vs) = readIOArray marks v >>= \ visited ->
                              if visited then
                                 search marks vs
                              else
                                writeIOArray marks v True >>
                                search marks (g!v) >>= \ ts ->
                                search marks vs >>= \ us ->
                                return ((Node v ts): us)

```

Even though the use of side effects in both definitions is basically the same, the `IO` version would be a violation of the given rule (it not being _“free of side effects”_) - in this case the presence of side effects is of no consequence, as they cannot be observed outside the scope of `dfs`.

---

_[View the full topic](https://discourse.haskell.org/t/using-unsafeperformio-safely/4146)._
