Search code examples
scalaprogramming-languagesfunctional-programmingparadigmsjvm-languages

Efficacy of sticking to just the functional paradigm in Scala


I recently bought Programming Scala, and have been reading through it. The language definitely isn't what I expected! Specifically, it seems to implement just about every programming language idea I'm aware of, outside of Lisp macros and Haskell's type-level side-effect segregation.

Frankly, it has me somewhat overwhelmed. Though I suppose it's nice to have so many tools at my disposal, I was really just looking for a strongly-typed functional language on the JVM. I imagine I could probably use Scala that way, but I imagine if I interact with any libraries or go through anyone else's code, I'll be running into a lot of this advanced (for me) OOP stuff--traits and "object hierarchy linearization," all this abstract and overriding business, singleton, package, and companion objects, implicit conversions... not to mention the various syntactic shortcuts and sugars.

People often bemoan programmers who try to shoehorn one language's style into another, for lots of good reasons. But not all languages are as multi-paradigm as Scala, so perhaps its community has a different view? In F#, for example, there seems to be some leeway in programming styles and how much OOP you use. But just from reading I'm not sure if this is a good philosophy for Scala as well.

Can more experienced Scala programmers help me out here? Edit for clarity: Basically, can I safely use just (or mostly) the FP features of Scala without worrying about its advanced OOP side?

Sorry for the rambling question!


Solution

  • I think that there is most certainly a solid point in this question. It is illuminated by looking into how any library might handle exceptions.

    If you interact with a Java library, any method may throw an exception. This could be either explicitly, via a checked exception - or transparently (from an API perspective), via a runtime exception. What are you supposed to do about this, as a programmer who might be trying to use the more functional Either type to indicate failure (or scalaz's Validation)?

    It's not at all clear to me how this will play out in scala (i.e. approaching the problem and choosing the purely functional approach). Certainly it is likely to produce many different styles of coding. That said, there is much that is rich and useful along the functional side of scala which you can pick from; and it is certainly possible to have this mix of functional and imperative code in your program work alongside each other. Although a functional purist may of course disagree about whether this an optimal situation.

    For what it's worth, I've found that the application of functional paradigms within my programs has improved my code no end. As I haven't tried either Haskell or F# I couldn't tell you whether the net result is better or worse.

    But it wipes the floor with Java; and to get that on the JVM (with the practical advantage of coexisting with all our Java libraries) is a killer app, from my perspective.


    At the edges, as you begin to use scala's functional side more, there are a number of issues which you will run into. These are most obviously:

    • the lack of implicit function currying (i.e. equivalence of A => B => C and (A, B) => C)
    • the lack of implicit function tupling (i.e. equivalence between an n-ary function and a 1-ary function which takes an n-tuple as a parameter)
    • the lack of inference for partially-applied type constructors (i.e. the equivalence of M[A] with, for example, Either[Int, A])

    Both of these issues make what should be pretty and clear functional code, ugly and obscure.