> I use Haskell to do rapid prototyping of various tools we are building, ultimately to be delivered in python.
Off topic:
Do you feel the code comes out better when you do it that way?
I'm going to share a story I've shared a couple of times, but no one really saw
it. I wish it was about a more real word application, but unfortunately I
haven't had the opportunity to write those in more than one language to compare
and contrast.
I took an intro to game programming class in college as an elective for fun and
the professor had us implement this old text based game called Hunt the Wumpus 3
times. The first time was text based, the 2nd time was 2D, and the 3rd was 3D (aside
from a semester-long group project). I remember the instructions mandating that
it is sufficiently OO (object oriented). I didn't think anything of it at the
time and everything seemed fine. Note we using C# at the time because later we
were going to use a framework like Microsoft's XNA. I ended up using Monogame
which is based on XNA Framework. Basically it's a lower level framework compared
to something like Unity.
One thing that stood out to me was I was unable to reuse anything from the text
based game in the 2D one because it had IO intermingled in the code and depended
on blocking to get input from the user. The 2D version was using a game loop and
was more event driven. That was my first time doing anything like that and it
ended up a buggy mess that barely worked right. The third time in 3D I think I
pretty much had to start from scratch again, but I got better at the event
driven nature of the thing and it turned out ok (it worked).
Fast forward in time and I am learning Rust for fun and decide to implement that
same text based game because I want to know what it feels like to program in
that language vs C#. I thought it turned out was great until I did the same game
in Haskell. Still blows my mind today how that language forced me to think about
things differently. If I remember right the Haskell solution was 1/3 the code
(measured with tokei) (2 source files and 1 test file vs about 9 source files
and 4 test files). All the IO ended up near the main function instead of spread
out all over the place, and it's not just concise syntax that reduced the amount
of code, but a simpler solution in my opinion. The game logic became just a
bunch of pure functions in a small library that moved the game from state to
state in an immutable game object.
I haven't tried it, but I imagine I would have been able to reuse the game logic
in a 2D game because the logic wasn't coupled to and dependent on IO blocking.
I think the purely functional nature of Haskell, especially the type discipline
around IO effects, drove me to a better solution. It's kind of funny in
in retrospect I find it hard not to just blame myself for over-complicating it.
Some of that does come down to lack of experience at the time. However, I work
professionally in C# and most of the code I see seems like an over-complicated
zoo with IO and partial functions everywhere.
If your interested you can judge it for yourself:
C# text based:
https://github.com/willbush/hunt-the-wumpus C# 3D with primitive shapes:
https://github.com/willbush/hunt-the-wumpus-3d Rust text based:
https://github.com/willbush/wump Haskell text based:
https://github.com/willbush/hwumpI have the 2D code in a private repo because it's such a train wreck that I
didn't want anyone to see it. I really don't care anymore so I can open-source
it if anyone reads this far and cares to see it.
I later realized the architecture I ran across is basically this:
https://blog.ploeh.dk/2016/03/18/functional-architecture-is-ports-and-adapters/