In this episode Neeraj and Jasim cover wide range including functional programming, static typing, Hindley-Milner type system, reasonML, clojure and Elm.
Neeraj: Hi everyone. I am Neeraj from Big Binary and today I am with Jasim. Hi, Jasim.
Jasim: Hello, Neeraj. Hi.
Neeraj: Hi. So, why don’t you go ahead and introduce yourself?
Jasim: So, I am Jasim and I’ve been programming for about ten years. I’ve mostly been doing a lot of dynamic typed programming in Ruby, JavaScript. And I’ve recently been working on typed languages, mostly on ReasonML, which is a dialect of OCaml, and also a little bit of Elm, last on the edge. So, I generally wanna talk about what it is to be programming in a type system coming from a dynamic background, and then understand what are the specific concrete reasons that programmers, on day to day basis, can enjoy from doing typed.
Neeraj: Okay, so I’m good. So, first thing first, let’s start with a lot of people might not be familiar with ReasonML. So, do you want to say a few things about what is ReasonML, and more specifically how it is different from OCaml?
Jasim: Yes. There are two axes in which we classify programming languages. One is based on the type system, that is statically typed and dynamically typed. An example of a static typed system is Java, C, C++. Dynamically typed languages include Ruby, JavaScript, Lisp, Smalltalk, list of all dynamic typed languages.
The other axis is are they functional, or are they imperative? There’s also another class of language, it’s called the logical programming languages, PROLOG and languages like that. But the most dominant paradigms in programming are these two.
OCaml falls into the statically typed, functional programming languages category, while other programming language that is known for being functional is Clojure, which is a sort of Lisp, which is functional, but it is dynamically typed. And OCaml and Haskell belong to the same family because both of them are purely functional, they have a similar syntax.
They also have a similar kind of type system called Hindley-Milner type system, something which we can… Mostly, it was a research project in the 1970s, I think, where they were trying to figure out how to express mathematical theorems, how to create a theorem program in the French University in Rheims. And they realized that the language they developed for this particular requirement can be also used to express programs in a more accurate, or a correct faction. So that is type functional programming, and OCaml is what came out of that.
Initially it was called Standard ML, I think it was just Caml Light, which became OCaml. So, there are a bunch of languages in this family, but OCaml is the most popular. And Reason is a new syntax on top of OCaml. There is nothing different about Reason oand OCaml, it’s exactly the same runtime, exactly the same compiler. All they did was in some spaces they added some braces. So, if you think of the coffee script in JavaScript, coffee script acts some semantics on top of JavaScript. The syntax is slightly different, it adds classes, it adds hetero-functions. But Reason does not do any of these things. Reason is a straightforward transition from OCaml, so you can actually use a program to shift between both. In fact, there is a Chrome extension that can convert any OCaml snippet on internet into Reason and viceversa. So that is easy.
Neeraj: I will interrupt this time and say too, what is the motivation? I’m sure that—first of all, who are the people behind ReasonML?
Jasim: Reason was created by Jordan Walke and Cheng Lou, and a bunch of other folks at Facebook. The motivation is that OCaml is a very powerful language, but it has been kind of limited to very small circles so far. It has been around for 20 years, but it does not see the kind of adoption that it likely deserves. And Jordan prototyped React, he’s the author of React and he prototyped React initially in OCaml, it’s because he came from University of Washington, where they teach Dan Grossman’s Programming Languages course, where his course was OCaml.
So, it’s which university you studied in, which languages you wrote first and that influenced you. And he took it to React, he took it to Facebook. There was already a team in Facebook that was working with OCaml for creating static analysis tools. There’s a pretty decent language research department in Facebook, and they created Reason because they wanted to support frontend programming with the statically typed language. And the syntax of OCaml would be a big turner for most programmers. So, they modernized the syntax.
So, if you look at Reason as it is today, it kind of restates JavaScript. The constructs are very similar, you have got ‘let’, you have got ‘if’, you have got braces. So, it is more of a modernization, it is to make this language in a consistency familiar to the largest group of programmers out there, which is frontend programmers. They also want to give first class support for frontend programming, so they have broaded React, the first class bindings for React, so you can create frontend applications in Reason today quite efficiently. It is kind of leading edge, but it works really well.
Neeraj: So, it is backed by Facebook, and I’m sure there are other people beyond Facebook, also. So, but because it is associated with Facebook, I’m sure the interoperability with the React components would be a high priority, and would be as seamless as it is possible to have that kind of interaction. Is that right?
Jasim: Yes, it definitely is. So, the only thing we need to worry about is there is a mapping from the dynamic types to static types. Because any data that comes into the Reason world needs to be statically typed, we have to express what these types are. We have to define them upfront. So that level, that exists in any sort of environment, where a dynamic end statically typed system in plot. So, that is there. Otherwise, the in drop is quite intense.
Neeraj: So, you were saying something about the programming model where static typing is there, and there is a dynamic typing, and you… go ahead and continue with that part.
Jasim: Yes. So, the question that I hear when I speak about Reason, or statically typed functional programming in general is why static typing? Isn’t it even more harder to build… can you prototype really fast? Because most people want to quickly try out something using a ripple, or just write things down, and then come back and stop till unorganized. And in static typing, I don’t really know the shape of the system that I’m building. I’m exploring as I’m figuring it out. Is this even possible in static typing?
So, I used to have exact the same question. So, this question comes from not understanding what kind of static typing the OCaml and Haskell world has. Because we have been confused by the type that we see in languages like Java and C++. It is the object oriented typed system. The interesting feature of that type system is that type and classes are kind of high indicative. There is no separate notion of type in those systems. So, to create a new type you define a new class, and type checking occurs based on are you passing in an object of the same class as the function expects?
So, that is a very weak form of static typing, which forces you to have very rigid systems. There is this old grinning joke of Java having an adaptor factory, adaptor virtual, adaptor patcher. So, this kind of things happen in bad—not badly, yet weak type systems. What Haskell and OCaml does is it lets you type the shape of your data. So, it’s assembler saying type User equals {Name:string; Age:integer}. That’s it.
You don’t have any classes to define, there are no… you don’t have to worry about sole principles, or single responsibility, or liskov substitution. None of these things come into play. You just create the final type and start writing your code. And you don’t even have to annotate these types, because there is a type inference mechanism which figures out by looking at the shape of your data that this belongs to a certain type. So that helps you write code which is a prototype kind of a code, which is kind of a throw away code, but it really is not. It forces you to think upfront about your data model. And that is a good kind of thinking.
What we do generally when we just keep going forward in a dynamic environment by just adding more code after the other, somehow we’re just going to a certain direction that we think is correct, is why do we build this throw away? In fact, even after a lot of design in the past that I’ve done, after you write a lot of code, most software that I write in dynamic systems is throw away. But I want to build systems that last in terms of after I build a system, I want that to be a wealth, scoping this sort of wealth that they can use in extent. I don’t want it to be thrown away, I don’t want it to be a pack of cards—which a static type system is helping a lot to me, in my experience.
Neeraj: Did you happen to watch the key note by Rich Hickey of the latest Clojure Con, which I think happened a week or two ago?
Jasim: Yes, I did.
Neeraj: Oh, you did? Okay.
Jasim: Yeah.
Neeraj: So, what’s your thoughts about about the…? I was… I will say that…
Jasim: He’s a very smart person. So…
Neeraj: Yeah, so go ahead. And he’s a smart person, but… I sense a ‘but’ coming.
Jasim: So, he is… it’s very hard to have the conviction in any of these things, to me personally, because what I knew six months ago is very different from what I know today. And I would have claimed at some point that angular is the best thing that has happened to the Internet, and then after one year, after having some experience, I would have changed my opinion. So, opinions are–
Neeraj: You’re going to get some hate mails on those, okay.
Jasim: So, of course, yeah. So, my concern is basically… what he said makes a lot of sense, which says that there are multiple types of systems, which is a one kind of system is a compiler, and compiler is a simple system, because it takes a large global string, which is a sourced code, adds a lot of pure transformations on them, and returns you in the last global string, which is a final geometric group. There is no IO, there is no evented system, there is no concurrency, there is no parallelism, now all these things are there. So, it is a simple system, it is a pure foremost computation, that is it. But we’re just talking about systems that are situated in the real world.
It [unintelligible 0:10:32.0] terms for the world, it makes requests to the external services, there are probably events happening. So, this is the kind of systems which has been building that he wants to build in this project. And in that context, what he says is a static types doesn’t makes sense. That’s the kind of idea that I got out from watching that talk. But I do wonder if he has worked in the kind of systems, in the kind of static type systems that Haskell and OCaml has. And now I’m not qualified to ask this question, because he probably has, he’s got about 20-30 years of experiences, he knows what he’s talking about. But there is also another kind of really intelligent programmers, where UI [unintelligible 0:11:05.0] missions and practical programmers who say the types do work.
And then we can only go beyond personal experience. So, from my experience with types, it helped me write code when I didn’t know a lot about programming, but today I prefer static types over dynamic types. And Rich did not give a lot of reasoning for why static types doesn’t make sense. And most things that he has ever spoken about in static type systems was about C++, he comes from a very strong CBB background.
So, maybe his bias against the kind of types that he was forced to use in that language. Recently, I was speaking to someone on the internet, and they were also saying that Clojure is amazing, even though he did one year of Haskell. But in terms of that, he works on his day job in Java, and so he likes to interact with Clojure a lot and he hates Java’s type system. So, he likes dynamic language because for the last 10-15 years, he has been writing languages like Java, where I have been writing a lot of dynamic code in Ruby and JavaScript and I need the safety of type systems. So, that’s generally—I think it’s a matter of personal experience, personal opinion, and also some amount of hubris, because you need a conviction, you need some conviction in your own beliefs to go and build something like Clojure, something amazing as Clojure. So, that is my general opinion.
Neeraj: Yeah. So, for some of the people might not be fully aware of what kind of type system we are talking about. So, for briefly I will describe that then. In the case of Java, when Jasim is saying that it is based on the class name, I think the technical name for that is a nominal type system, based on the names. So, let’s say that there is a name, a class called Person. So, when we are passing a Person, then the object has to be of the class Person, or the children of Person, or descendant of Person.
So, the type checking is very… I don’t know, obtuse in the sense that it just looks at the name, are you Person, are you a children of Person or not? And that’s it. Where in the case of Haskell, or Reason, or Elm, we have a structural type system, meaning that you defined your type as Name and Email, and tomorrow if you pass another record—and record you can think of as a hash, and if you pass besides Name and Email and Admin true, the system will accept it. Because when the system is not– correct me if I think that’s how at least Elm works, and I think Haskell also works the same way. I’m not sure about it.
Jasim: Yeah, I think Reason also has structural typing, but you can have multiple types of the same structure, in that case you are guaranteed explicitly what you want, but otherwise it’s also structural typing.
Neeraj: So, in that case, if you pass extra parameter, they’re just ignored and the things will go, so you can… it’s more based on the shape than the name of the class.
Jasim: I think Elm works like that. It’s sort of like duck typing in Ruby, it looks like—okay, I need these values in this record, do the excess and then coming things, it ignores what doesn’t exist. Reason though has to match one to one. So, if you have an extra column, or if it doesn’t have all the columns you need, then it won’t match, the types won’t match.
Neeraj: True, true.
Jasim: It’s still structural typing, but one is I think exhaustive. Or they call it row polymorphism, and I’m not quite sure what the terms are.
Neeraj: Yeah, so what the structure weight are was the velocity with which he was against the type system, the types don’t give you in the real world. To me, the thing is that in the real world you need to keep molding, you keep changing. The only thing that is constant is the change. So, you keep changing it, but the problem with the dynamically type system is that when I change something, the only protection that I have is my test.
So, think about this world, where I think that we are very soon going to have 2018, soon the self-driving cars will be on the road, but if I make a typo who is gonna catch it? So, in order to catch my typo, I might need to write a whole test. I’ve never written a single line of code in Clojure, but from the old it looks like it’s similar to as from that point of view, the dynamically type system.
Jasim: Yeah, it is dynamic type. Exactly.
Neeraj: Then the only protection I have to catch my typo is a test. Now, that is too high a price to be paid for the test. And that’s why the Ruby world, when I came from Java to Ruby got, ‘Oh, we have so much test.’ And I was so elated, I said, ‘Wow, look at this wonderful community, and people are great, so much test.’ But now I am a wiser person, I know I still love Ruby community and that’s where I do most of my work. But now I know that the reason why they have a lot of test is that the reason is different. Because we need to have it, it’s a dynamical type language.
Jasim: Yes.
Neeraj: And I feel like now that we’re coming close to the 2018, well, I mean the computers need to do more. And humans are not good at catching all the places the implications will be if I change this thing, because the requirement has changed, now I need to change from type to this, or initially I was passing these and a few items, now I need to pass an array. Now, what are all places I need to change? It’s very hard to catch, unless you have test. And I think that’s where the computers and compilers are better at it.
Jasim: Yeah. So, that is the reason why we use a computer, to do the manual work for us, right? This is just clerical work. Are my commas and are my punctuations correct? Am I using the same names? Am I passing the same kind of type that is—so there the notion of type already exists in the system, that is implicit. If the types don’t actually match, then something wrong is going to happen, and you won’t even know until runtime.
And sometimes you don’t even know. So, what a static type system does is it does this clerical manual labor for us, it just verifies whether, okay, your function needs a name. Is it getting a recall which has a name in it? This is not rocket science, right? This is what computers do for a living.
When we use a computer to add 100 numbers versus doing it manually, it is just that difference. And I am quite surprised that we haven’t seen this before, we haven’t talked of this before. We have seen static types in Java, but because of it too obtuse, we always figure that the trade off in a dynamic system with test is better than using a rigid type system, like in Java.
But we’re fully seeing a more powerful type system has been an eye opener. Also, tests are not a good idea. I am not paid to write test, unless I am a tester. I am paid to write programs that work, create value in the world, and tests are a support system. I cannot put a system into production without test, because I want to build robust systems that work under multiple conditions.
But my primary job is to program, I’m most happy writing code that does things. In the dynamic type system, you have your ratio of test, so usually people say 70+ or 80%+ test coverage, but in some parts of the system that there’s a lot of things going on, for every 20-30 lines of code, you’ll have 100-200 lines of test, a lot of expectations and associations. And if you want to change something in your code, your test will fail, that is good.
But now you have to go and manually change, you have to hunt and pack, you have to seek out these particular places and change the names of these variables in 200-300 different places. That has happened to me multiple times. So, what happens is test slows you down. Now, there is this whole field of testing, theory of testing on what you should test and what you should not test, send just the messages that you pass to the system that don’t test what is going on inside, make sure that when you’re sending a request to an external world, that request is happening, but you don’t assert on its listeners.
There are a lot of rules, just like object oriented world has rules on how to test. And when someone says that, okay, my tests are making me slow, my tests are too big, it’s very hard to refactor my code because I have to change my tests a lot—they would give you the not-to-escort argument, they would tell you you are not doing your testing correct. But if you try understanding what correct means of testing is, it’s like reading a very esoteric, philosophical New Age book, where anything can be everything, there’s no one completely. In type systems, I am now able to test functions in a very simple manner, it’s just a black book system.
I have a function, I call it, what do I get out of it? And these functions compose neatly well, so I can have test at multiple granularity levels. But my test to call ratio is very little, every single test I write is actually valuable, it doesn’t slow me down at all. And when I refactor my code, my test gets refactored with it. Which means if I change the name of a variable, or a function, I don’t have to go and manually change my test. That is taken care of. That’s all I have to be saying about test.
Neeraj: So, I will say one thing I like about our rightly [unintelligible 0:20:07.0] Rich Hickey is that, in one of the talks he asked to the people is that, ‘Raise your hand if you use a type system.’ And so people lift their hand. ‘And keep your hand up if you think that your program doesn’t have any bugs.’ So, I think that intentionally he is a smart guy, intentionally he is conflicting the word ‘correctness’.
Jasim: Yes.
Neeraj: If the compiler says that this program is correct, compiler is saying that if you are adding two numbers, you are passing two numbers. Now, in the body of the function you can do a minus b, and the compiler is not going to catch it, and that’s what you will write the test for. Right now, what I think is that we are writing the test for that are we passing a and b are the proper integers or not, or if you are handling the situation where they are not correct. And that’s why in the JavaScript world we see so many ‘Undefined is not a function’ kind of error.
Jasim: Yeah.
Neeraj: Because undefined is not a function, not that the programmer has done anything wrong in the body, it’s just that when the message is being passed, incorrect types are being passed. And when you refactor your code, or change your code, or the requirement changes, it’s next to impossible to catch all those things. So, I think that…
Jasim: I’ve also seen where an unfortunate programmer, who had acquired a sum function that took a and b. He had to add a and b to get them done at asserts. He had to do a parse int before… only because he don’t know what is going to come in, and he had to do this because some sentry or some adjust preparing logging system gave you, ‘You cannot add a string’– or sorry, the outset will let you add strings anyways. But this thing happened to me, because I had a state in my system which was an integer value, but users could also pass it—it was an ID. Users could also pass a custom ID from the URL.
And I was using React Router, which would extract this ID to me and give it to me in a variable, and I forgot that this was a string. And ID, usually in my system has always been an integer. And suddenly I have a function where I’m getting ID as a string, and I don’t know what is happening. The first instinct is always to just parse it and then clean it up, but ideally you should handle all data cleaning and passing in the boundary of a system, clear it all properly, so that it still doesn’t need to be homogenous, it doesn’t do all these different feed checks. But it’s so hard to figure out what is going wrong.
If it is a statically type system, the moment I extract the ID from a string, and the ID still remains a string, it won’t even compile. Because they tell you, ‘What are you doing?’ That’s the manual labor for you, we’re just making sure that when your function expects integer, you’d better pass an integer. So, there’s other kind of errors that you get in JavaScript where it’s so hard to catch. In simple cases it’s already hard, but in very complex scenarios, where you have a lot of data flowing into various nets of hierarchy, it’s so hard to figure out what type is happening, what change is happening in the system. So, you just go write different C code, in that particular function you just message it to whatever you want, and then you go your merry way.
Neeraj: True. But in the parses of being defensive, what we do is that whether we don’t know it’s a string or integer we still parse it, but during the parsing process there could be an exception and we just don’t know what will happen, and we just raise it at the… or let the system catch it, meaning that it will go all the way to the top, and then things will blow up, or the system, whatever the global level the team has decided to catch there, it will happen. But I think that kind of programming is not very… this kind of defensive programming will add a lot of rather late calling, and at no point of time you are confident that your call is correct.
Jasim: Exactly.
Neeraj: That you will have the right type to work with.
Jasim: Yeah. Or locally you have the right type, but you have no idea why do you have to do this parsing bit. Like where is it coming, what is happening before this? So, you’re always very worried when you’re touching anything. It’s just like a pack of cards, anything can blow off at any point in time. So, you’re very careful with this kind of software.
Neeraj: So, I think, if I understand you correctly, Jasim’s advice is that people who are doing Java, just try something like Haskell, Elm or Reason, where there is a better type system, fairly appreciated, right?
Jasim: Yes, absolutely. I would recommend Elm for beginners, because the documentation is all targeted towards people without any software background of type systems. You don’t even have to read… So, if you start reading the Haskell book, that’s a really well written book, but they open with a chapter on lambda calculus, and that is necessary I would say, because until you understand what that stuff is, there’s a little bit of math there, but that is pretty much the math for the first parts of the text. But until you understand that, it might be a little hard to understand why do you use recursion, for example, in string filtration. Or can you really express all the computation that I’ve been doing in my pretty programming using this functional style?
So, these will help you understand these things, give you solid foundation. But for Elm you don’t need these things, you can just start reading the documentation, that’s about 20 to 30 minutes of your time, that entire Elm guide. And then you can just start building rich web applications right off the bat, I was very surprised by that. It’s kind of similar for OCaml as well, but in terms of you don’t need to know a lot of abstract category theory. And I think they’re wonderful things to know, category is definitely wonderful, because it’s a mind-blowing experience to kind of understand what a monad is. I’m still in the phase of understanding what that is. But it lets you write programs that can compose in a way that you ve never imagined, the programs that can have error conditions, that are asynchronous, that takes input, all these things you can write in a very composing manner, which you cannot do without the help of monads and category theory. But you don’t really need that as a beginner, you don’t need to be scared of it by the amount of things you already don’t know before you start. And Elm does a fantastic job here, it just lets you be productive with a minimum amount of hassle. The community is realizing that’s coming, so thanks a lot, Neeraj, for the thing you look into that. Because initially I was quite skeptical of the language and everything.
Neeraj: Elm is great, but I am really encouraged by the direction of JavaScript. For example, I think that Redux in itself is a great tool, but it’s also a great way to get inside into a slowly walk towards the functional programming, because pretty much a lot of people who are using React, they use Redux, and they don’t know that they are using some of the concepts which are functional programming things, but after having used Redux you ask anyone, and they all like that, ‘Oh, there is no mutation.’ They don’t know.
Jasim: Yeah.
Neeraj: Because when they did something, things don’t work. So, they slowly start appreciating what exactly the Pure functions are. And if you take the Pure functions, then Elm or ReasonML or Haskell, slowly you can explore more in that area. And as part of that out exploration, what happened is that I spent some time looking at Elm, but after that I scaled backed when I found out about Ramda. So right now Ramda, if you are using say Lodash or Underscore, both of them are wonderful libraries, but you should definitely give a look to Ramda. I talked a lot about Ramda to a lot of people to the point where I wrote a blog about why you should be using Ramda, so we’ll put a link to that.
Jasim: No, but I’m curious, can you tell me? I’ve watched a few of Dr. Boonian’s functional programming with JavaScript videos, and I think he’s a big fan of Ramda. And I also heard from a friend of mine, where he says Ramda is a much better library for functional computation and compared to, say, Lodash. And Lodash also has lodash/fp, which is similar to Ramda. So, what is it? If I have underscore.map that I generally use from Lodash, why should I use any function of Ramda?
Neeraj: Yes, underscore.map is not the problem. The problem is something like, let’s say, you need to do conversion. So, you have two functions, you need to take it, and then you need to apply it to a particular function. So at least there are 30 or 40 different kind of functional constructs out there, all the way from Ramda to when, to conditions, then particle. So, it’s not like you are going that, you will do prop this. Then I have not even used the higher much more complicated concepts, like lenses, etcetera. But all those things are available to you in the JavaScript world itself.
In fact, I will say to the point where when I started using Elm, to me I was not learning much of the functional concepts, because I was still getting used to the type system. And functionals are so ingrained over there, you don’t feel like you are making consciously a choice. While here, when you’re using Ramda, like you, a lot of people are writing JavaScript code, so you’ll have a better experience. And so, say there are certain functions you are writing, right? So, you are taking some arguments. If you were to be using Ramda, and using the proper calls over there, problem matters, you can make it a point-free. In fact, your goal should not be to make everything point-free. But at least there you will learn it better, because you can see the non-point-free version, and the point-free version.
Jasim: Okay. So, I heard that you had a ‘if’ you can write conditions in Ramda.
Neeraj: Yes, if-then…
Jasim: I see, yes.
Neeraj: …If-else. So, you can do if-else, and if-else the first argument is the barrier gate. So, it will take the first, and then it will execute function one, otherwise it will execute function two.
Jasim: Is there an either in that? Like there’s something called an either monad where the left S handles, the left floor handles errors, right floor handles the success conditions. Is there an either monad involved in that?
Neeraj: I don’t know, I will have to check that. I think I’ve used if-else, I’ve used where, I’ve used when and a few… and of course, there is curry, so you can make any of the functions which are, like taking five parameters. But it’s not like a stupid curry where, okay, then you have to pass each parameter one by one. Instead three arguments are there, you curry them, then you can pass either one, two, all three, and it will work.
Jasim: I see. So, do you see yourself writing JavaScript with Ramda and a type system? Or what are you more interested in, from what… So, there are two angles, so one is a function angle, one is a types angle, and how do you think of both? Or what is most important to you?
Neeraj: I think both of them are equal important at this time to me, personally. Because where I feel like coming from… and so now we are getting into the aspects of typed versus so far, we have been talking about the type. The functional concepts are great. In fact, we just wrote a blog about where we are using recompose. So, we use recompose in our gap component, and the great thing is that now that we have the component is there, but instead of showing the component, we need to show a spinner. Now, in the typical imperative world, what will happen? And if you’re writing a standard react component, then we’ll say, ‘Okay, if the state is loading then show a spinner.’ So, we need to go into the gut of the body of that function, and we are making the change. While here you can recompose—you can just compose the two components, and we can build a hold over component. So, the previous component, which is fully tested, does not need to change just because there is a need to show a spinner. So, I’m saying that the coming from the imperative where, this functional world is a much better world. But I’m saying that why stop there, when I have seen the light with Elm?
Jasim: Okay.
Neeraj: So, both of them are beneficial and I’m saying that we should take both of them. So, personally I would like to move toward Elm. However, I feel like the whole software programming world will be much better if today everybody in the JavaScript world starts using Randa. Because what will happen is that that will prepare you better for the functional world, and you will start appreciating what the functional things are. For example, let’s say that you have a lot of JavaScript repetitive components. It’s much easier to see what exactly you’re doing in the functional world rather than every single time you need to go to the gut of it and you can do it. And of course, with the JavaScript has come advanced, so you can do a lot more things, that there you have something like map and for each, etcetera. But still, you can go a lot further than that and make your code a lot more functional and a lot more modular.
Jasim: So, I’m definitely gonna check out. I’m not sure, because I don’t really want to write JavaScript anymore, but I’ll still check it out so that other people who are interested in writing and trying out functional concepts for the first time. But would you recommend someone who is already writing JavaScript, should they check out Elm versus Ramda? Or Ramda more than Elm?
Neeraj: No, I don’t say Ramda any day. The reason is that I will say Ramda, because Elm is a big change, you need to convince your team, you need to have the whole ecosystem and the learning curve is a little bit high. While Ramda today you will see the benefits of it.
Jasim: It’s just a library, you can just put it in the side, using it, and then a lot of people will say, ‘Well, it is cool, it’s nice,’ and then you slowly add up, you just take Redux on. So, when you said Redux, the whole React in Redux was a Trojan horse for functional programming. And interestingly, generally backend developers used to have this idea, that backend design was more complex, and frontend is not real programming. I’ve heard this, and I’ve been a guilty of this very early in my career as well, when I didn’t really understand that programming is a craft that spans a lot of things and areas.
And right now, backend… if you’ve been writing a lot of reels and building big complex applications, there are a couple of ideas that you specialize on the backend. One is how to actually model a large system, so that is I would say that this argument meets a particular object or a descendent in Ruby is probably a kind of your bible, and the descent pattern’s hooks. And all these existing [unintelligible 0:34:00.0] on original design is there, so you get better at handling domain complexity, that is one aspect. The others, you get into schedule relations, you get into the sewer systems, you get into message parsing and Kafkas and queues and handling systems at scale. So, this is the part that a lot of people take in the backend world.
But in the frontend, even for a very simple backend system, for record the application, that is probably maybe a project management tool, the frontend today is a lot more complex, it requests a lot more programming and repeat, a lot more thought about the shapings of beta, that the frontend is becoming a lot more complex. And I don’t think the market has caught up, because most of the good programmers are entrenched in the backend world. And it’s mostly young programmers who have been writing code for maybe three-four years, whose first language was JavaScript, whose first database was MongoDB, whose first web framework was Express JS. So, they really love the mean stack, to use a short form. These kids have been at the forefront of the functional world use, and that’s very interesting to me, because nobody would have thought that Express JS and JavaScript would be a fertile land for Haskell and PO script and ReasonML, and to see that kind of an option. And now we have to go back from frontend into the backend well and tell them, ‘Look at this thing. This is amazing, just start writing, it will be inviting, and just come and take a look here.’ So, I think Redux and React helped make the transition. It is definitely not intentional, but it is pretty nice that it did.
Neeraj: Absolutely, 100% agree with that. And on the backend side I see that there is a little bit of traction there, a lot of people from Ruby community have moved to Elixir and they are getting exposed to their functional concepts, and it seems that a lot of people have moved to Clojure and they are liking it. But I will say that, since pretty much everybody writes in JavaScript, there is absolutely no excuse not to use the Ramda. Once again—for example, Ramda has simple concepts like r.type and r.compose, and it’s really nice that it drops in at the top, and then Pype is… And if you configure functions—and once again, you don’t have to go to a great extent to make it point-free, but if you make it point-free then that’s pretty awesome, because a good chunk of our functions, they just take some arguments, do a few things, when we don’t even need to take the name of anything. And in this array, whenever it’s… by default it’s curried, and then you just pass it and then it just works, which is really beautiful.
Jasim: One thing that I want to caveat, because we’re having this conversation, is type functional programming for everything. And because I just spoke about the backend people looking at the functional aspect. But I still think that reels, for example, is still one of the best ways to build backend applications, because of the ecosystem, because of the language, because… or maybe Django is pretty good, there is available in PHP. And I think all these systems are, if I have to build a new web application today, I might personally pick OPM from OCaml, or try to figure out what the [unintelligible 0:37:17.0] for Haskell is. But for actual projects, for timed projects for people who are building business applications today, I still think that the ecosystem is important. So, we can’t just go and say that you picked this language, but their needs are probably to build a web application, and that needs to align with what the liabilities are capable of, or the ecosystem is capable of. So, I won’t say that everybody should come and start at opting type functional programming, but it’s interesting as a class and as a programmer, if you definitely look into it. It will into the frontend then open, you should definitely look into it, but if you’re building an application that makes money, that’s… just pick the right tool with the right ecosystem for that. Does it make sense to you…?
Neeraj: Yeah, and it absolutely makes sense. This is the question—this is an argument from more fellow people who have been in the Ruby world at least for couple of years. So, once you know Ruby on Rails, then what next? So, what next is down to explore more, and then you will gain some perspective, and maybe you will come a bit in your own conclusion, or maybe you will create a new programming language. And then who knows?
Jasim: Yes.
Neeraj: Yeah, the people, when a lot of JavaScript, is absolutely moving at a phenomenally good direction, with– just today I found out that there is a proposal to how to do Expression. Before that, also, I think two weeks back we had Twittered that JavaScript is [unintelligible 0:38:37.0], and somebody has proposed to have a pipe operator. So, these things…
Jasim: Yes, and piper magic.
Neeraj: And piper magic, exactly.
Jasim: Yes.
Neeraj: And I remember that they, when coffee script has been born and there’s a lot of debate should React adopt coffee script or not. But I think a lot of credit I give to coffee script for moving us in the right direction, as opposed to a little bit like that in all those things.
Jasim: Yes.
Neeraj: And the amazing thing about the coffee scripts author was that he was building coffee script as to learn how the compilers and all those things work. So yeah, so definitely check out all the things and you will make your own view. And same thing is in the Elm world. When I look at Ivan and when I follow some of the discussions, it’s pretty interesting to see how the language is shaping, because all the… not all the—most of the people coming from Haskell, they come and look at it and they say, ‘What is this? This is a watered-down version of leg Haskell, this is absolutely useless.’ If you’re building a new language, build even better than Haskell kind of things.
Jasim: Yes, yes.
Neeraj: And the JavaScript guys are coming and say, ‘Oh my Goodness, this thing is so hard!’
Jasim: This is alien, yeah.
Neeraj: And they’re saying that… Specifically with Elm there’s another debate, because I think the PureScript and BuckleScript and ReasonML, they have taken an easier path as far as the FFI is concerned for a functional interface. You just call alert(foo) and it will work. But not in the case of Elm, because it has to go through the pools, and it has to do all the data passing, etcetera. So if JavaScript guys come and say, ‘What? I cannot even do a simple function like alert, I have to do all these things of scripting, and the pool and all those things.’ So, it feels incredibly hard to them, and I sympathize with Ivan and the science he has taken, because he is crushed between the…
Jasim: …two worlds.
Neeraj: Yeah, and us. But that’s the beauty!
Jasim: So, I think he is deliberately going not as away from the Haskell kind of thing, because from his very initial talk about Elm, he wants to build a practical language that most programmers today can use, without understanding a lot of complex theory that goes behind the system. And I think it makes sense, because if you are coming from the Haskell world, you have PureScript, which is more or less Haskell, but except that it is script. And I hear that it is also more cleaned up than in Haskell. So, Elm, I’m happy Elm-like system, I’m happy that I can point my friends who are doing frontend development and say, ‘Just go, walk through this guide, read through this book, write that sample code yourself. And suddenly new things will pop up in your mind, you can get a different perspective.’ And one interesting question I ask myself every few years is, if IOS articles crashed today, if I was IAMSL, what advice would I give myself as a programmer to become better at this craft? A few years ago, it was after watching Bill Morrison’s talk about refactoring Ruby and signed him as his book. It was mostly figure out how to name things better. So, if you have a big chunk of code, just add as much names.
Neeraj: That goes out the window type system.
Jasim: Yes, now it is type system. Now I’m like, ‘Go, man!’ What is the fee within type systems? And he will become a better programmer without doing much. So, I’m quite happy that he [unintelligible 0:41:56.4].
Neeraj: So, Rich Hickey in his talk he metioned that, okay, what is a typed system? And people time a, b, c… That’s now how the Elm world works. The Elm world has names.
Jasim: So, he said many things that seemed factually wrong. He was talking about position and arguments. So, he said the position of the argument is important. It is not, right? You can have records, you have name records, I think he was talking about the product types, where you can have int_string, which means that your data value has to have an int first, and then string second. That is a product type, but in most languages you have the syntactical sugar if giving it names. So, instead of this typing int and string, you can say Age, which is an integer, and Name, which is a string. And the compiler will remove both these tags when it compiles, so it goes away at runtime. So, what you especially get is basically a product type without any record names. But while you program you have this. And he chose not to mention this at all, and there was a debate in the Haskell community where… was he purposefully doing this? Or my question is basically does he know some of the dynamic thing? Because I definitely think he has talked about this a lot better than someone like me, who has only been doing this for about six months now. And so, has he actually programmed in Haskell, OCaml for enough time to appreciate? Has he built a beginner system in these languages? Or is there something hidden in what he said? Because two of the most insightful talks in programming that I’ve heard was from Rick Hickey. One is ‘Simple made easy’, the other is ‘The value of values’. So, in ‘Simple made easy’ he had this concept of a breed, a complex breed, a tangled up mess versus more number of threads, but they are all straight. And there is an amazing visual analogy to think about programs I like. It’s okay to have say, for example, duplicating code without too many indirections and conditions inside, versus having one big function that does 100 checks and conditions, which is really hard to understand. So, that talk was very similar for me, personally. And so, when Rich Hickey says something I take it really seriously, but this time I really couldn’t understand what he was trying to say, so… And I’m afraid to criticize him for this, because I don’t really know to criticize enough. But there’s definitely something off about that talk, either there is something incomplete, or he was purposefully creating a straw man about type systems and its issues.
Neeraj: So we’re talking about the type systems, and since both of us have a background in Ruby, so this time in RubyKaigi there were two talks about the type systems. And after the conference, Ned Marcospek [0:44:36.0], the person behind realspeed.co, he twittered that he is not in favor of any of the existing proposals for the type systems. And Matt said he twittered that, ‘I 100% agree’. So, it seems like Matt does not like any of the existing proposals for the type system. But he did say that, that Ruby 3 will have some kind of type system. So, I’m not sure which stage we are in in the Ruby world, where we are going to have the type system. And if we are going to have it, which way it will go. Because I understand there are a lot of choices, as was presented into us through the talks. And after that also, after the end content was a strange look, and there also there were a few presentations on the type systems for Ruby. So, there were a lot of proposals on the table, it needs to be seen which one to take, and obviously Matt and his team has much more insight into which way it should go. But a lot of…
Jasim: I’m looking forward to what they come of it, because Ruby is a phenomenally wonderful language, because everything is a message. I can really appreciate it today, looking backwards, because it’s a… that’s it, right? You can… For example, in JavaScript you have prototype systems, so to create functions you have to go into a hash and add an entry there to create a new function in an object. But in Ruby nothing is static, there is no hash that stores all the materials and attributes inside the system. There’s only passing messages. Or, each object is just something that receives and sends messages, and that is it. It’s really wonderful, which lets you do all sorts of metaoperators dynamic to the core. And if it also had a static type system, like an optional type system, like JavaScript also, like Flow or TypeScript it may quite be wonderful. I’m hoping they do static type system and given more of Matt’s days are, I think it might come out really nicely.
Neeraj: So, anything that you would like to talk about and we haven’t covered?
Jasim: No, I think we have talked enough, but I just want to also talk about sum types quickly, because that is one of the biggest revelations to me after doing type functional programming. Now wherever I look I see a sum type.
Neeraj: What is a sum type?
Jasim: Sum type is basically called a union type…
Neeraj: How do you spell it? Sum, S-U-M, or S-O-M-E?
Jasim: S-U-M, yeah, S-U-M type.
Neeraj: Okay.
Jasim: So, what sum type does is, imagine you have a user who can be a guest or who can be an admin, or who can be a normal, regular user. And generally, what you do is you create a type defining the role as a string in most languages, and then you have something like a permission management system that checks whether this user is a guest, or is an admin when they try to do some operation. What happens when you add a new type of user to the system? What happens is you forget to handle all the possible cases, so it goes into production and then you realize, okay, or some recognize that this is not possible, there’s a security issue here, then you’re gonna add it. So, one thing about programming software system that are released over the last ten years is that they always grow. There is this idea, there is a saying that the best code is code that is not written, which is a very wise saying, it tells you that you should consider carefully before you write code, because every line of code is a maintenance segment in the future. However, the value of a system is in its size. So, you start up with a very small system, but the more features it has, the more effort has been put into it. We are basically being paid to actually write code. Writing code means a system grows. So, we have to always think about a growing system, and when a system grows, there are two kinds of things that can happen. One is adding a feature, two—modifying an existing feature. So, then you add a feature, for example you’re adding a new kind of user into the system, you want to have confidence that the system will work correctly. Test won’t give you that candy, but this test will not understand a growing system, that is meant for a static system that you have designed in a certain manner. When you have some types, the system knows that this particular type has been used in so many places. And so, whether you add a new kind of entity into the system, you have to handle it in these many places. That is amazing. You suddenly can actually go change things in a static type system, because that’s a manual bookkeeping for you, so that all the names are correct. You can also go add features, because there is the sum type that will take care of reminding you where are the places in the system that this change is going to affect. That is a huge revelation, and after learning that, my Java sometimes improved a lot. So, even when I write a simple JavaScript function, I’m acutely aware of the sum types that I’m missing. And so, I make a statement sheet in most cases in user interfaces. So, for example, if I make an Ajax request, it has to be of a state where it is being empty, then initial state, then a request has been sent, a request has been successful or failed. And this state is made explicit in the system, instead of just putting in some records. So, this kind of thinking I’m able to take back into all of my programming, which is one thing that is completely useful about learning a type functional language.
Neeraj: So, is that somewhat similar to union types in Elm?
Jasim: That’s exactly the union type, yes.
Neeraj: I see.
Jasim: So, you just call sum types, or variants, or union types.
Neeraj: I see. And so, for implementing this in JavaScript, are you using some package, or some library?
Jasim: No, I just created a string and then I made the control flow very explicit. So, for example, if you have to show a spinner while the request is being sent to the server, one way of doing it is if is_loading, or is_request_being_sent, or something like that, you’ll have a boolean value to express it. So, usually we will do that. But, instead I will create a string which has a state explicitly written. And then instead of doing if is_loading, I will check what’s the status. So, what happens is when for example if there’s an error, then you might usually have an error field. And so, if you say if is_loading or if is_error, then show it to us, right? Now your system is all tangled up, your control flow… it’s very hard to visualize what is going on. Instead, you make these states very explicit.
Neeraj: So, when we are using recompose, which we are using in some for our project, what we do is here we will have a lot of components, and with the help of recompose that’s what we do. So, the first let’s say highest order component gets to evaluate it, and if the is_loading_state is true, then it just renders the spinner, otherwise it passes the control to the next component, which will do the real work. So, in this way more and more, and the way you combine these two is using recompose as another call, a function called compose. So, is this something similar to that, which is home grown?
Jasim: This is sort of the same, yes. I think the core idea in both cases is we’ve dispatched things from a higher level. So instead of inside the component, we are not distingue whether it is loading or not, but we are making that assumption at a higher level, and then after that the flow is very linear. There is no conditions below that. So, in one level we make sure, if we dispatch the correct component in recompose. So, in that sense this is, I think, same. But if we use union types, or sum types, then instead of using a Boolean you can use a string, which can be more simple, because what happens when multiple Booleans combine together? For example, the page is loaded, but there was an error, or there was a error of two distinct types that you want to handle separately. So now you have error is true and error code is 404 or 500, right? Instead, if you had these errors all part of this explicit string basically, it might become easier, it won’t have to combine multiple Boolean values, yeah.
Neeraj: Sounds good. Do you have any blog, or anything…?
Jasim: Yes. I think NoRedInk wrote about something similar today, which I think we discussed earlier. So, I point over that, and probably we can also write up some notes and then maybe some quote samples for this.
Neeraj: Okay. That sounds good. I think this sounds like a good place to end, right?
Jasim: Yes, definitely. It’s about one hour, it’s been a long call.
Neeraj: Yeah, definitely. So once again, it was really nice sharing with you.
Jasim: Yes, it was.
Neeraj: Take care, bye bye.
Podchaser is the ultimate destination for podcast data, search, and discovery. Learn More