Three years before Haskell arrived, there was Clean, a lazy functional language that solved the interactivity with the world outside its computational graph by using unique types (which means nodes could be shared in the computation graph) rather than Monads.

I used Clean in the late nineties (and even wrote a paper using it as a backend). It worked great and had seamless access to GUIs.

At that time the language went by "Concurrent Clean" even though the concurrent aspect was tied to the transputer that didn't took off.

These days, with CPUs with dozens of hardware threads available as consumer products, it might be worth bringing back the concurrent backend.

The one-stop shop for all things Clean is the Clean wiki but the key section for this project is part 5 of https://wiki.clean.cs.ru.nl/Functional_Programming_and_Parallel_Graph_Rewriting.