I'd change "binding functions to data" to "binding functions to types." The "data" is an object of a particular type. The binding to the actual data (object) can take place at compile time or run time, depending on need. IMO that makes it a bit less weird and more just shifting the position of a parameter.
Well, the reason I say binding to data instead of binding to type is that runtime polymorphism on instances is one of the selling points of OOP. I think its a little overrated but that is a good reason to use OO if you need that functionality. If you're only attaching functions to a type there isn't much difference between "thing.fn(x)" vs "fn(thing, x)"
Having just come out of a datastructures class, this is the view that seems the most useful to me. ADTs in general seem to be very well expressed with classes, and I think it is exactly for the reason you mentioned: they are just systems that need to be able to define the ways in which a user is allowed to interact with the data.
There are so many times you don't want to bind functions to the data they operate on, and languages that force OOP always make it painful
The other thing OOP gives you is type taxonomies, but frequently those are an anti-feature. Almost every experienced developer I know thinks inheritance is usually a bad idea.