It's hard to know what you're missing if you haven't tried it. If you see patterns moving data around, it's nice to abstract those out. And higher-level languages give you more powerful abstractions.
All computing "consists of simple operations that move data from one place to another", that's essentially the foundation of computer science.
It seems you're trying to say "most software isn't that complicated", which obviously isn't true, in fact, the opposite is true: most software is a complicated mess.
Have you never had a thing that could be EXACTLY one of two things, ever? And you wanted the compiler to make sure that, anywhere you used that thing, you had to take care of BOTH of those possibilities? That's one of the main uses of ADTs.
Absolutely: ADTs and general-purpose crud stuff are a perfect fit. It's the delicate numeric stuff where typed functional languages are at their least helpful (though I think still somewhat better than imperative ones, except at the ultra-high performance end).
Is the complex stuff you get done with Java the same as the "majority of software engineering" you describe? I'm having trouble reconciling those two claims ...
Though most of my time is protobuf in Java, I still wouldn't mind having an ADT or two for when I got lists of things and the things aren't exactly uniform but I don't want to make a type hierarchy.
Yeah I could emulate it, but it's much more verbose, and the signal to noise ratio is bad. Ex, a four line Haskell ADT could be 40 to 100 lines of java, and you gotta think things through a bit more. Instead I might have two fields which are Optional and specify an invariant in the comments.