DEV Community

How to use Dependency Injection in Functional Programming

Jesse Warden on January 16, 2022

Dependency Injection is a technique to make the classes in Object Oriented Programming easier to test and configure. Instead of a class instantiati...
Collapse
 
redbar0n profile image
Magne

How would you compare Elm and ReScript? And which do you prefer?

Collapse
 
jesterxl profile image
Jesse Warden • Edited

which do you prefer?

The only reason I use ReScript is because Elm doesn't officially work on the server, I use AWS at jobs not Lamdera, and Roc isn't ready for prime time yet. That said... I've started to love their "we're imperative and don't care about Category Theory nonsense" style/attitude these OCAML kids have. I've never met a community like that before, it's neat, I'm learning a lot from them. You can learn more about my journey in my video about JavaScript to ReScript.

Ok, comparison.

Elm works on the browser, not the server. ReScript works on both the browser and server. There are ways to hack Elm into a headless state, but it's not fun. It is fun to watch others do it, though.

Elm has no side effects, so all functions are pure. ReScript is like TypeScript; it just compiles to JavaScript, so doesn't have a runtime engine like Elm does. Thus, ReScript's side effects operate just like JavaScript, and there is no I/O Monad type insanity to worry about. Instead, you have side effects everywhere insanity just like you do in JavaScript. This makes ReScript require more unit tests. WAYYY less than JavaScript to be sure, but you need stupider tests around side effects that you don't need in Elm; meaning you have to focus on testing more things.

Elm is good enough with it's types to ensure no runtime exceptions/errors, ever. ReScript is even MORE strict, yet still allows unsafe things through, and has escape hatches making it dangerous if you're not careful. For example, Elm has Maybe, specifically Nothing to handle what we in JavaScript would handle for null or undefined. ReScript is so strict and accurate about compiling to JavaScript, it has 2 completely different modules (well 4, but...) to handle both Undefined and Null in a typed way, including ways to convert back and forth. It really is a symptom of OCAML being a lower-level system language sometimes, and people from that style of language thinking in exacts. That said, it's not thorough, because if you convert an undefined to ReScript's version of Maybe called Optional, you'll get a None, but sometimes you'll get a Some in the case of null vs. undefined. It's better to use the Js.Nullable class to safely convert when you have to deal with JavaScript types coming in like user input or parsing weird JSON. I bet some people love this level of accuracy, and claim it is needed for some reasons, but I prefer Elm's simpler way of dealing with undefined/null: erasing it from existence vs. ReScript giving you thick gloves so you don't burn yourself playing with fire.

Elm's compiler is fast; faster than TypeScript. I've not used it for a gigantor project yet, but I've seen various ways to speed it up so I'm not too worried yet. However, ReScript is light speed. While I tend to do teency microservice/functions in Serverless to ensure my code doesn't get into a large monolith on purpose, I just LOVE how fast I can iterate in ReScript. It's unbelievable how fast the compiler is in a monorepo with like 3 Lambdas and dozens of supporting files. This is the main reason I don't want to use TypeScript compared to ReScript; it's just crazy fast.

I like Elm libraries better. Both languages assume a lot so if you're a beginner it can be pretty overwhelming to even get started. Like, GraphQL library for Elm doesn't tell you how to generate; they just assume you know it's a CLI and will run cli --help and not the default loading from Github. Elm's whole focus is on the beginner and making the complex simple, and many of the library authors are in education or passionate about pedagogy, so this is the exception to the rule most times. My issue with ReScript is were still in this weird time where Reason and ReScript split, but you can still use the Reason libraries in ReScript. It's not really clear, and sometimes when I try, things don't work and there are no errors and I'm like "wtf do I do now?". This is par for the course for JavaScript stuff, though, so I give a ton of leeway to that community; Elm, the opposite, and that works well, because their libraries... always work.

The Elm compiler error messages are better, EVEN IF don't type your functions. Yes, with types they're better, but ReScript ones are nowwhere near as user friendly. Even if you do data-first programming, ReScript still is like "yeah, somewhere your stuff is broke". "Hey, uh... ReScript, how about a... you know... line number to start my investigation, eh, what do you think?" "No, good luck!" Elm's all line numbers, and formatted, and colors, and pretty, and friendly, and hinty... it's just night and day.

I like how Elm has no overuse of (), no need of {}, semi-colons, and isn't as mean as Python about spacing. ReScript has MUCH less need for {}, and doens't need semi-colons either, but you still sometimes have to type it like TypeScript to get better compiler error messages, un-confuse the compiler, and I've grown to like the ML Elm typing style better than the Java esque inline style:

Elm:

add : Int -> Int -> Int
add a b =
  a + b
Enter fullscreen mode Exit fullscreen mode

vs ReScript's inline

let add = (a:number, b:number):number => a + b
Enter fullscreen mode Exit fullscreen mode

ReScript's style is to NOT type because the type inference in OCAML style compilers is just so good, but... maybe I'm doing something wrong, but I've found it's just better to type because the compiler gives messages I can actually read, and sometimes it requires a type to get "unconfused" in long chains.

I like how Elm is data last programming like normal Functional Programming, and ReScript is data-first. I also don't like how ReScript has this data last baggage and makes new packages that are data first to be more friendly to JavaScript developers. I think it's the same stupid tactic the JavaScript devs are trying to do with the Hack style vs. the F# style in the new pipeline operator. If you're a functional programmer, you'll learn to love data last, and all the literature matches. But nNnnNNNnooooOOOo, that's not how the OCAML kids jam. Just hurts my brain to switch back and forth between Elm and ReScript is all, minor nitpick.

I like how Elm has 1 architecture and "that's it". ReScript is like "Dude, we're just a fast compiler with better types than TypeScript and we support functional things". Which means you could use it in Angular or React even if both code bases were heavily Object Oriented. Some find that amazing, I'm like "ugh". That said, it makes it easy for me to use in Serverless, Server, and CLI style architectures, including the Browser when I have to do some things in JavaScript because Elm doesn't support it (i.e. document.cookies). This is just where Elm and ReScript aren't really comparing apples to apples; one is a language, compiler, framework, and runtime whereas the other, ReScript, is just a language and compiler. There's no need for a runtime "because JavaScript" or for a framework "because JavaScript".

... that said, as a team to be full stack ish? They're the shit. I love it.

Collapse
 
redbar0n profile image
Magne

I just LOVE how fast I can iterate in ReScript. ... This is the main reason I don't want to use TypeScript compared to ReScript; it's just crazy fast.

Is it the speed of the type inference that is slowing you down in TypeScript? Or is it the Webpack bundling, or TS transpiling? Curious what fast refers to: HMR, type inference, or transpiling? Or all?

Have you tried Vite?

"Vite uses esbuild to transpile TypeScript into JavaScript which is about 20~30x faster than vanilla tsc, and HMR updates can reflect in the browser in under 50ms."

vitejs.dev/guide/features.html#typ...

The only thing I don't think Vite addresses is the type inference in the IDE... but how slow are they anyway?

Thread Thread
 
jesterxl profile image
Jesse Warden • Edited

When I run the compiler in watch mode. TypeScript takes seconds, ReScript takes milliseconds. No webpack, hot hot module reloading, just writing writing code so I can immediately go node theFile.js or npm test:unit.

No, I haven't tried Vite, thanks for the link. My issue, really, is... me. 10 years ago, I learned of TypeScript. As a new Flash/Flex refugee, I was looking for something that had strong types and would compile to JavaScript since I still wanted to do web development, just not go back in time 5 years using JavaScript compared to ActionScript 3. Back then, compilers/transpilers were fringe, JavaScript the language didn't have as many features + browser support as today, and most of the community said "You don't need classes and types". While I didn't agree, it was still hard to implement this stuff for client work if you weren't a sole contractor architecting your own projects for clients. Once Angular RC1 came out, TypeScript was more mature and solidified to write not just UI's but back-end code, CLI's, and libraries. Angular RC1 is also when I stopped being an OOP fan, and started learning more Functional Programming. 10 years later today, TypeScript still isn't very friendly to a Functional Programmer. The language is heavily focused on OOP developers, or heavily Object based code bases that have a lot of internal state and side effects. Despite the herculean efforts of fp-ts, and the massive growth in the job market for TypeScript acceptance... I don't really care, I don't like it.

ReScript gives me the guarentee's I want and the speed I want, with zero configuration or having to muck around with compiler settings, bike shed with a team what settings we should/should not use, etc. It's friendly to an FP programmer and has many FP features built into the language and standard libraries.

Thread Thread
 
redbar0n profile image
Magne

10 years later today, TypeScript still isn't very friendly to a Functional Programmer. The language is heavily focused on OOP developers, or heavily Object based code bases that have a lot of internal state and side effects. Despite the herculean efforts of fp-ts, and the massive growth in the job market for TypeScript acceptance...

That is a very compelling reason to go for ReScript over TypeScript indeed. TS can too easily slide out into something you don't want, and everyone on a team being guided into doing the right thing is good.

PS: check out ts-belt if you have to use typescript, it's inspired by and built with ReScript.

Thread Thread
 
jesterxl profile image
Jesse Warden

Nice, thanks, I'll check it out.