I hear they are good, make it easier to maintain code-bases. Most often I reach for python to get the job done. Does anyone have experiences with functional languages for larger projects?

In particular I am interested to learn more on how to handle databases, and writing to them and what patterns they come up with. Is a database handle you can write to not … basically mutable state, the arch-nemesis of functional languages?

Are functional languages only useful with an imperative shell?

    • Kacarott ( Kacarott@aussie.zone ) 
      link
      fedilink
      arrow-up
      13
      ·
      9 months ago

      I highly agree with the sentiment. Learning languages of different paradigms is sort of like travelling to visit other cultures to make you a more rounded, better person. Learn a functional language (lisp/Haskell). Learn a concatenative language (forth/Factor). Learn a logical language (Prolog/?). Heck even learn an assembly! (I suggest RISC-V).

  • subversive_dev ( Transform2942@lemmy.ml ) 
    link
    fedilink
    English
    arrow-up
    13
    ·
    edit-2
    9 months ago

    Got to put my plug in for Elixir. Built on the legendary Erlang runtime, looks like Ruby and secretly a Lisp under the covers. The Ecto database library blows every other ORM or tool I have ever used out of the water.

    Regarding mutability, I would argue the runtime has everything you need like message passing, software transactional memory, pleasant I/O and the best exception handling you could imagine

  • masterspace ( masterspace@lemmy.ca ) 
    link
    fedilink
    English
    arrow-up
    10
    ·
    edit-2
    9 months ago

    Most major languages these days are multi-paradigm languages that can do procedural, functional, or object oriented coding.

    C#, Kotlin, JavaScript, TypeScript, Go, Python, Swift, etc all fall into this bucket.

    Java has made a lot of efforts to support functional programming, but it’s still not first class.

    I would argue that these languages adopting functional coding as a first class citizen has made dedicated functional languages somewhat more obsolete, but they also paved the way and set the standards for the general languages that came after.

    On the web side of things, the most popular JavaScript / TypeScript frameworks these days are often fundamentally functional though, from React on the front-end to Express on the back end.

  • FishFace ( FishFace@piefed.social ) 
    link
    fedilink
    English
    arrow-up
    6
    ·
    9 months ago

    Functional programming languages can be extremely beautiful when doing a task suited to them, but extremely ugly and cumbersome when doing anything not suited.

    With an imperative language you can always fall back on C-style for loops and manipulating state. It may not be beautiful but it’s fine. But if you need to use an STArray in Haskell, every single access is through a verbose function call without even array access syntax.

    So I would suggest either finding a toy project to do in a pure functional language, or else use a mixed paradigm language and make maximum use of its functional features.

    On databases, yeah database access is by definition stateful. It can be encapsulated in a monad, but that just means it’s not a good fit for pure functional programming.

  • Oinks ( Oinks@lemmy.blahaj.zone ) 
    link
    fedilink
    arrow-up
    5
    ·
    edit-2
    9 months ago

    Is a database handle you can write to not … basically mutable state, the arch-nemesis of functional languages?

    Well, kind of. You would treat it the same way you would treat pipe/terminal or file IO: You write some impure functions that do the actual IO (database calls), and some pure functions that work on your data types. Then you compose them together to make an application. Hopefully most of your code is in the pure part which means you can test it without having to mock the world.

    This honestly isn’t all that different from how a well written imperative code bases turn out. You generally don’t want to put all of the IO and all of the business logic into one super function or method or even class, because that makes things really hard to test (and hard to reason about too if you go far enough).

    You can have actual in-memory mutable state in functional programming too, you just don’t get it on every variable by default. At least in Haskell you would usually achieve this by using a type that does it for you, like IORef or ST or MVar or TVar. The reasoning above applies to those - You would generally use them sparingly, when you really need mutability (e.g. to pass data between threads), and not everywhere.

  • It’s good to have some experience with them even just to know what tools may work best for a situation. I’d suggest something close to what you already know, C# -> F#, java -> clojure or scala, declaritive -> ML or Haskell, etc. dynamic vs static and strong vs weak typing systems can have a big impact on how you think about programs. Debuggers vs REPLs vs compiler warnings vs generic logs are all going to be different too on top of the paradigm like functional that will have different approaches. Minimizing the other differences makes it easier to focus on and learn the functional stuff.

    If you look at samples of a bunch and none are clicking I’d start with any that has dynamic typing, REPL style like common lisp, scheme, elixir. They are simple to get started with coming from python dynamic typing and options for interpreter & compiled, and you can add dependency management and interop and other stuff on top later. RDMS SQL is generally a static typed, declaritive style language. If you want a similar functional language look at ML, Haskell. But even in functional languages you’ll usually use a library or driver or language feature specifically for interacting with RDMS, you may use pandas in python and datomic in clojure.

    The big things to focus on are understanding common idioms like combining functions in call chains using basic functions map, reduce, & filter, etc, creating new objects with charges instead of changing in place (non mutable), and higher order functions/function composition that lack of mutability restriction allows.

  • TehPers ( TehPers@beehaw.org ) 
    link
    fedilink
    English
    arrow-up
    3
    ·
    9 months ago

    Is a database handle you can write to not … basically mutable state, the arch-nemesis of functional languages?

    Access to an external database is a kind of effect. In functional terms, you’d use a monad to represent this, though in Koka you’d define an effect for it. In either case, it becomes part of the function signature.

    A “pure” function could instead work around it by returning (without executing) a query, accepting a state and returning a new, modified state, or otherwise returning some kind of commands to the caller without directly querying the database.

    • Oinks ( Oinks@lemmy.blahaj.zone ) 
      link
      fedilink
      arrow-up
      3
      ·
      edit-2
      9 months ago

      A “pure” function could instead work around it by returning (without executing) a query, accepting a state and returning a new, modified state, or otherwise returning some kind of commands to the caller without directly querying the database.

      At least in Haskell due to lazyness this is (almost) always what happens. A monad is just one kind of deferred computation, with an operator >>= (“bind”) that happens to prevent compiler reordering or deduplication. Any IO actions are only executed when main is evaluated and no earlier. Strict functional languages to my knowledge don’t need monads to do IO since they don’t have the same issues with evaluation order that Haskell does (though they might want them for type safety purposes).

  • MagicShel ( MagicShel@lemmy.zip ) 
    link
    fedilink
    English
    arrow-up
    2
    ·
    9 months ago

    Closest I’ve actually used is Kotlin, but honestly I’d rather use functional paradigms within Java instead.

    I’ve watched a lot of videos on Haskell and Scala, and I think understanding what they are doing and why can only make you a better programmer.

    I use the Java functional package all the time. Understanding how to compose functions and define the input type and output type (either of which could be functions) is sort of awakening. Programming by side effect like with a method void doStuffWith(Foo foo) stands out as red flag if you are familiar with FP, but evidently it looks perfectly fine to someone exclusively familiar with OOP.

    That all being said, I don’t think FP is clearly superior. If you go all in, I suspect you’ll find yourself running into familiar problems wrapped in unfamiliar shapes. I think a very happy medium is to define data classes with only getters and setters instead of rich objects. Business logic can then be moved out to some handler, controller, or operand classes that operate on interfaces which the data objects implement.

    Mostly, FP forces you to think about some hard things and deliberately implement them instead of seeing what the default behavior is and fighting it when you don’t want it.

  • I mostly work in Go, but I helped maintain one project written in Elixir for a while. It was rather interesting. It’s certainly a different way of thinking. It does reduce the risk of certain side effects but, as with everything, it has its own downsides.

  • They don’t really let you do anything you couldn’t do in Python, they just let you write more elegant code.

    Personally I find ML-style languages to be difficult to read. They deliberately leave out a lot of the punctuation that makes code readable leading to code that just looks like a stream of words.

    Rust is I think the best option here - it steals most of the good ideas from functional programming but has saner syntax.

    Also you seem to be conflating pure languages with functional languages. I also made this mistake because Haskell is probably the best known functional language and it’s also pure… But they’re different things. OCaml is functional and not pure. You can use mutable variables to your heart’s content.

    TL:DR learn Rust not Haskell or OCaml.