from Hacker News

How we secretly introduced Haskell and got away with it

by philippelh on 3/3/17, 12:11 PM with 182 comments

  • by mybrid on 3/3/17, 3:15 PM

    In the 1990s I did research on the efficacy claims of object oriented programming versus procedural programming. This article bares a striking resemblance in the claims. Case study after case study showed that object oriented code had less bugs due to compilers catching bugs, etc. However, almost every study was similar to this report: it was a re-write from procedural to object-oriented. There exists strong evidence to suggest that throwing away ones first prototype produces the same results as to benefits comparing object-oriented versus procedural programming. The conclusion of my research was the same as others: unless one is comparing the same project written from scratch without any sharing of design or code then these studies claims are correlation, not causation.
  • by daxfohl on 3/3/17, 4:13 PM

    I'm just starting with Haskell and PureScript. So far I'm liking the latter better. It solves a few of their gripes with respect to strings, laziness and records, plus has a more granular/extendable effects system and cleans up the standard typeclass hierarchy. Also `head []` doesn't crash.

    Of course Haskell is more mature, has support for multithreading and STM, compiles to native, so it's more performant. But PureScript integrates with JS libraries and seems "fast enough" in many cases. I think it's more interesting as a project too: the lack of runtime and laziness means the compiler code is orders of magnitude simpler than Haskell's, so I could see a larger community building around it if it catches on.

    Given that they were on Python earlier, I wonder if PureScript would have been a better choice.

  • by sid-kap on 3/3/17, 2:59 PM

    The comparison between Stack and Python build tools is striking:

    > No messing around with virtualenvs and requirement files. Everybody builds with the same dependency versions. No more “works on my machine” and “did you install the latest requirements?”.

    I wonder why the Python ecosystem, which is much more mature, doesn't provide a build tool as delightful as Stack (which is less than 2 years old).

  • by slezakattack on 3/3/17, 4:35 PM

    "It is said that Haskell programmers are a rare species, but actually the majority of developers at Channable had used Haskell before."

    Could you imagine if this wasn't the case? The hurdle to actually get people excited about a language such as Haskell especially moving from something like Python would potentially be huge. Kudos for already having that problem solved.

  • by gaius on 3/3/17, 6:52 PM

    At one company I experimentally wrote OCaml and named the resulting native binaries whatever.py. None ever looked at them. So there is alot of scope for shenanigans.
  • by Twirrim on 3/3/17, 4:18 PM

    While it's an interesting look at a change you introduced, that blog title might not come across quite as intended.

    If you're having to "secretly introduce" tech, and "get away with it", that suggests there are unnecessary and unproductive constraints on your work; maybe even suggesting that you'd get in trouble for actually daring to make things better.

  • by framp on 3/3/17, 7:36 PM

    Glad to see Haskell used in production.

    It's kind of funny that build reproducibility (which was a major issue before stack) is one of the strong point.

    I wonder if, for your project, using cloudhaskell would have been more appropriate. I have a feeling some of the problems you found could have been solved with that.

  • by lima on 3/3/17, 7:08 PM

    You can deploy Python code as a static binary that includes the interpreter along with all dependencies. I heavily use this in production and life is great - deployment means copying one single binary, reverting means running an older one instead. No external dependencies, no pip upgrades, just libc.

    https://github.com/pyinstaller/pyinstaller

  • by techman9 on 3/3/17, 5:39 PM

    > No messing around with virtualenvs and requirement files. Everybody builds with the same dependency versions. No more “works on my machine” and “did you install the latest requirements?”.

    While this is nice, of course, I'm not sure that is outcome is unique to Haskell/Stack. It seems like you could accomplish a similar level of reproducibility by building a Docker image or bundling dependencies in some other way.

  • by arianvanp on 3/3/17, 3:45 PM

    I'm the author of the post. I'll be happy to answer any of your questions :)
  • by jwatte on 3/3/17, 11:58 PM

    Instead of using separate monad transformers, we use a single "World" that knows how to provide Redis, logging, iOS, and other typeclass instances.

    There is a RealWorld that runs on top of IO and a FakeWorld that runs on top of pure State for unit testing.

    This means that we have to wrap every single API into our own "SupportsRedis" and similar APIs, but in the end I think it's worth it! Unit tests are super fast and not intermittent at all.

  • by yawaramin on 3/3/17, 4:16 PM

    Nice article. Out of curiosity, what does your write with? Vim/ghc-mod? Emacs/Intero? IntelliJ IDEA/plugins? Atom/VSCode etc.?
  • by javajosh on 3/3/17, 7:46 PM

    In case anyone was wondering, the 'stack' command in the article refers to https://docs.haskellstack.org/en/stable/README/. Which actually looks kind of wonderful.
  • by kisstheblade on 3/3/17, 7:00 PM

    Always when I see haskell demonstrations eveyrthing looks like just interface declarations.

    You can do beautiful interfaces with eg. java also. But where is the meat where anything actually happens? I rarely see that in these posts. Yes I could look up the source but I don't have time to read through it randomly.

    This looks just so nice and stuff just magically works?:

    runWorkerLoop :: (MonadBackingStore m, MonadLogger m, MonadIO m) => WorkerState -> m WorkerState

    And monads to boot! (are monads haskells equivalent of java factories? I kid, I kid :)

  • by contravariant on 3/3/17, 4:07 PM

    > The issue here is that we cannot run runWorkerLoop and runFetchLoop with forkIO, because we don’t have the right transformer stack.

    Am I understanding correctly that this is because, while you can lift e.g. runFetchLoop to something of type IO m (), it's not possible to convert use forkIO on it since it requires an input of type IO ()? Isn't that just a consequence of the fact that Haskell has no possible way of knowing if your side effects can be contained in the IO monad?

  • by davedx on 3/3/17, 4:47 PM

    Good luck with hiring!
  • by osi on 3/3/17, 3:41 PM

    makes me wonder how long they would have lasted had the initial implementation been done simpler (ie, not in their PyDatalog fork).
  • by hota_mazi on 3/3/17, 7:56 PM

    > but if we could get it done, there would be no going back

    The naïveté in this simple statement is so cute.

    The list of concerns is also pretty naïve. The main problem you are going to encounter with this project is hiring. If you want to grow this project or if the main developers leave the company, I bet it will get rewritten in a different language in no time.

  • by guptaneil on 3/3/17, 3:07 PM

    It looks like jobmachine is a private repo, maybe don't include the url in your blog post :)
  • by mehaveaccount on 3/4/17, 12:26 AM

    Actually if you wanted a statically typed compiled functional language of Haskell while keeping the declarative logic paradigm of Prolog, then the Mercury programming language was made exactly for you!
  • by xyzzy4 on 3/3/17, 5:56 PM

    Haskell is a bad language, in my opinion, because you can't tell what the O(n) run-time is for any operation. Instead you just have to "trust" that it'll be fast enough.

    More on this: https://www.reddit.com/r/haskell/comments/1f48dc/what_does_t...

    All of the answers seem insufficient. Basically you can't estimate Haskell run-time unless you are very familiar with the internal Haskell engine.

  • by ctlaltdefeat on 3/3/17, 9:31 PM

    There are various mature options for scheduling jobs with dependencies between them.

    Why did you choose to write your own, regardless of the language?

  • by vorotato on 3/3/17, 9:26 PM

    I'd use haskell if it weren't lazy by default and didn't use Cabal. Aka I'd use OCaml/F#.
  • by eternalban on 3/3/17, 3:43 PM

    > Our lead developer Robert usually comes in a bit later, so we had about an hour to build a working prototype.

    I'm guessing he is a Python developer and likely he is no longer the lead.