Working in functional langs I just do DI with higher order functions.
I agree with you about service classes. I think one of the things that service classes do well that regular functional code does not is indicate to the consuming developer which parameters are meant to be provided by the environment and are largely static, and which are meant to vary per invocation.
Lisp does this instead with dynamic scope. But dynamically scoped dependencies felt too much like global variables to me. The service class instance has its scope bound to it and it won't change. But dynamically scoped functions always felt like the ground could get ripped out from under me at any time.
Service classes are "configurable functions", as I tell my team. With the advantage that you don't have to monkey-patch an import in another module to do a unitary test of the function, but rather you can inject mocks!
One thing I do insist on is that a service class either does something (calculate some value, retrieve some information, etc.) xor it coordinates service classes (parse value, then call the validator and, finally, persist value). This aims to prevent deep call chains where every function in between does a little bit and calls someone else, which can be hard to reason about.