Haskell is an excellent choice for modeling the kind of system you are describing.

However, like in any programming language, the way you model your system is heavily dependent on what operations you will want to do on it. And a functional programming language like Haskell helps you focus on that. Modeling the data is nice, but where are the functions?

Your types for Ambulance, Station, and Crew are simple and straightforward. I'm not sure why you then want to glob them together into one big SystemState. That kind of construction is indeed useful in certain situations. It's not surprising that it complicated things for you a little, though, because it is somewhat of an ad hoc mash-up. Whether or not it's needed depends entirely on the kinds of functions you'll be writing.

But the main issue here is how to use GHCi effectively.

What exactly are you trying to do in GHCi? I spend a lot of time at the GHCi prompt. I can divide that time into three categories: exploring functions to understand them better, testing and debugging functions to make sure they work, and performing one-off calculations using functions that I already understand and already know are working. I don't think I've used GHCi very much for just typing in data structures and having GHCi spit them back at me.

Still, for each of those three uses, I do need data structures. Usually the ones I need are simple enough that I can type the entire thing in one go. They actually don't have to be very simple for that - don't forget that you can type multiple mutually-recursive definitions in a single let statement by separating them with ';', and that GHCi supports multi-line statements with the ":{" and ":}' commands.

If a data structure I need is complex enough that I want to build it up incrementally like you were doing, there are several easy ways to do that.

To get a mutable variable that you repeatedly modify to build up your structure, similar to the way you would do it at the command line prompt for an imperative language, look at the Data.IORef module. If you are new to Haskell, I would recommend avoiding Data.IORef like the plague in your programming - it will always tempt you and it is almost always the wrong thing to do. But at the GHCi prompt, it's fine.

Truthfully, I almost never do that. Being lazy, I just use the up-arrow and other command-line editing keys to get the whole thing into one GHCi command incrementally.

And of course, if the data structure you are typing is actually meaningful and not a throw-away example, you'll want to type it into a file in your favorite Haskell editor rather than at the prompt. Then you'll use your editor's GHCi integration, or GHCi's ":r" command, to keep an up-to-date version of your structure available in GHCi.