Open collegeimprovements opened 4 years ago
Hi @collegeimprovements , nice to see that you are interested in functional programming! There are are a lot of resources, most of them are Haskell-related, but I guess this is not an issue if you are really interested how to make programs more beautiful. If you want just to dive in very quickly, I can recommend this article:
http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
In my opinion, Functors, Monads, Applicatives, Monoids and Bifunctors are the most basic, useful and widespread type classes in practical functional programming.
Wonderland is successor of https://github.com/timCF/category#category and is built using similar principles, just better and wider. But in link above you still can find useful article which explains some basic functional programming concepts with Elixir examples.
If you are interested in mathematical aspects of functional programming, there are beautiful lectures by Bartosz Milewski https://www.youtube.com/watch?v=I8LbkfSSR58
Also my friend @k0001 is writing a book about functional programming. But keep in mind that this book is oriented for non-programmers as well, so you can find narrative a bit slow if you already know something about programming in general https://atypeofprogramming.com/
There is another book, which I think the most complete guide about Haskell and functional programming today, but keep in mind that some part of it are really complex even for professional Haskell developers http://dev.stephendiehl.com/hask/
Quark, Witchcraft and Algae are another family of functional programming libraries for Elixir. They are done by people with some academical background for sure, but atm they are pretty abandoned and buggy, some features are not working in modern Elixir at all. If compare these libraries and Wonderland, it's obvious that the scope of Witchcraft family of libraries is much wider, there is a lot of stuff done but in my opinion they have a lot of disadvantages as well. The biggest one in my opinion is lack of encapsulation and wrong (in my opinion again) implementation of ADTs.
You can read about encapsulation problems in Elixir in another my articale https://github.com/timCF/calculus#calculus
In Wonderland this problem is solved. Also I implemented in Wonderland just small-small subset of functional programming stuff. Only things which have high immediate practical value. It's a small subset, but I'm trying to do it as much good as possible and as much as correct as possible.
Thanks for the brief comparison with the Witchcraft Suite. I had great success introducing Witchcraft on a current Elixir project. And, indeed, I've been reaping those benefits exclusively with Semigroups, Monads and Functors, which you'd (correctly) term a "small-subset of functional programming stuff".
I'd love to see a more detailed comparison (perhaps as part of the repository, ideally with examples of how different problems are solved in both), including your opinion on their approach to ADTs. Also curious if you recommend other Elixir libraries for ADTs (other than Calculus and Witchcraft's Algae).
I'm currently taking a break from Elixir to study Haskell. I'm about half-way through Haskell Programming From First Principles (HPFF), which I hope will make me more comfortable using Witchcraft (and bring my Elm to the next level). The above has encouraged me to try Wonderland to see if it's a better fit.
(Since this is a thread about recommended resources, my current thoughts on HPFF is that it's excellent if you have the time to commit to reading it and doing the exercises. I'm planning to follow it with Sandy Maguire's Thinking with Types and Manning's Haskell in Depth.)
PS: I find it fascinating that your consultancy rate for Haskell is 40% lower than for Elixir. But I guess at the Elixir rate, clients are getting a Haskell goodness/mindset thrown in as a bonus!
Well, I didn't dig much into Witchcraft/Algae/Quark, I just found that they are not working like I would like to see them work) Let's check how they define Maybe https://github.com/witchcrafters/algae/blob/39922c6f6ca67577921ab887ae4662ddf22e3d98/lib/algae/maybe.ex#L32-L35 Looks pretty, but of course, issue there is that Elixir don't have concept of sum types. Elixir have only product types. The most intuitive way to define new type in Elixir - to define struct or record (which are not really separate types btw). But let's assume they are. Elixir appreciate this assumption everywhere in codebase, for example: https://github.com/elixir-lang/elixir/blob/1c157bdc54223c54c503396f0709658203d059da/lib/elixir/lib/map_set.ex#L58 This "t" is shortcut for "type" and as far as you see, it's alias for struct. And this implicit assumption what "t" is alias for some struct is pretty much everywhere in Elixir.
In Algae this macro definition of Maybe expands into 2 separate structs: https://github.com/witchcrafters/algae/blob/39922c6f6ca67577921ab887ae4662ddf22e3d98/lib/algae/maybe.ex#L55 https://github.com/witchcrafters/algae/blob/39922c6f6ca67577921ab887ae4662ddf22e3d98/lib/algae/maybe.ex#L61 Which in terms of 99% of Elixir codebase should represent different type constructors. But both "Just a" and "Nothing" values should be values of the same type, which is not true there. One of the outcomes of this - they implement typeclasses (aka protocols) for "Just a" and "Nothing" values separately: https://github.com/witchcrafters/algae/blob/39922c6f6ca67577921ab887ae4662ddf22e3d98/lib/algae/maybe.ex#L168-L181
Using Elixir protocols as type classes is quite intuitive, but there is huge restriction in how Elixir runtime dispatch evaluation of protocol functions. Elixir taking to account just first argument, which is quite ugly and very restrictive in many cases, for example if you want to implement protocol not for type, but for pair of types (kinda like Haskell type families, but it's very very inaccurate comparison). Yeah, if protocol want to take to account more than one type - we are in trouble. Previously, I did couple of libraries which allow to do such things on top of protocols, but it was long time ago and they have nothing common with Wonderland, Witchcraft or any other smart stuff: https://hexdocs.pm/equalable/readme.html https://hexdocs.pm/comparable/readme.html
In contrast of protocols in Witchcraft, in Wonderland I'm using behaviours to implement type classes. It's pretty easy actually: https://github.com/tkachuk-labs/wonderland/blob/575cb23fa14b9adba5520b5e608e6029296d7b11/lib/wonderland/type_class/functor.ex#L5-L9 This is the only option which can work with Calculus types, because they have real encapsulation (I still think Calculus is the best Elixir library I did ever and very proud of it 😅). Implementation of particular type class have to be inside module where type is defined, or it will just not work https://github.com/tkachuk-labs/wonderland/blob/575cb23fa14b9adba5520b5e608e6029296d7b11/lib/wonderland/data/maybe.ex#L34-L38 This make existence of orphan type class instances kinda impossible (maybe it's actually good), and restricts extendability, but I can live with that.
I had great success introducing Witchcraft on a current Elixir project
That's really great! Because Elixir and Erlang community in general is not friendly for functional programming, and if you was able to proof that it makes code better - it's already a good job! I'm not sure why the situation with FP in Elixir is like this, but probably because Elixir and Erlang are untyped languages by default, and it's hard to reason about types and type classes without really having them.
other Elixir libraries for ADTs
There is actually one more library which is kinda predates Witchcraft: https://github.com/Qqwy/elixir-fun_land But generally, I did Wonderland just because I could not find Elixir FP library which I like :)
our consultancy rate for Haskell is 40% lower than for Elixir
Well, consultancy is not my main income, so I can encourage people to use right languages through pricing as well))) And so far, I'm writing in Elixir for a long time, almost 7 years, in contrast - in Haskell I'm writing just a bit more than year, so it's natural that my Elixir time is more expensive. It does not mean that it's better. In absolute values my Haskell code is better than Elixir, but software dev market don't encourage absolute values for some reason 😀
and bring my Elm to the next level
If you like both Elm and Elixir, you might be interested in this project https://wende.github.io/elchemy/
There are couple of other typed compilers/tools for the BEAM https://github.com/alpaca-lang https://github.com/gleam-lang/gleam
They give you types, which is already a big deal. But if you compare them with Haskell, of course functionality is very poor, no type classes, no exhaustiveness validations etc. I really want to see BEAM backend for Haskell compiler, but it not exist atm, and I'm not smart enough yet to do it, so I just switched to Haskell in general
Hi @tkachuk-labs,
What are some good resources to learn about functional programming that are used or can be used with
wonderland
?And how is this library different from witchcraft ?