Sure
* Your values wont be null. So if you have a type say Object, and a value x of type Object. x will never be null. If in some cases you need values that can be something, or nothing, there is a "Maybe a" type and an "Either a b" type (often used for errors, i.e. it is either an error of type a or a result of type b). This gives you a lot of control and expression around things that might not have values.
* Functions have no side effects. You define a function and it has inputs and outputs but it wont go off and do something else. You can be sure that your functions aren't modifying global state, navigating to new urls etc. even without inspecting the functions they call, and the functions they call.
How does anything get done? Well the desired effects are returned as data. And you can tell by the type what kinds of effects it can produce, and what it can't.
Now I spend a lot of time on C# legacy code thinking 'ah a public property, great who is calling that, what is this function calling, OK a,b,c,d. Now what does a call, ok a1 a2 a3 a4. Ok they look OK now what about b etc. Lots of detective work that is not needed in Haskell/Purescript because the type sigs tell you almost everything you need to know from an architectural point of view about what is going on, because there are no side effects of functions beyond producing data to be consumed.