Most active commenters
  • marvinborner(3)

←back to thread

389 points kurinikku | 12 comments | | HN request time: 0.643s | source | bottom
Show context
marvinborner ◴[] No.42164919[source]
They give a nice introduction to encoding state as pure functions. In fact, there are many more purely functional encodings for all kinds of data like trees, integers, sum/product types, images, monads, ...

The encodings can be a bit confusing, but really elegant and tiny at the same time. Take for example a functional implementation of the Maybe monad in javascript:

  Nothing = nothing => just => nothing
  Just = v => nothing => just => just(v)
  
  pure = Just
  bind = mx => f => mx(mx)(f)
  
  evalMaybe = maybe => maybe("Nothing")(v => "Just " + v)
  console.log(evalMaybe(bind(Nothing)(n => pure(n + 1)))) // Nothing
  console.log(evalMaybe(bind(Just(42))(n => pure(n + 1)))) // Just 43
replies(5): >>42166462 #>>42166688 #>>42166841 #>>42168370 #>>42173549 #
1. hinkley ◴[] No.42166462[source]
[flagged]
replies(4): >>42166679 #>>42167412 #>>42167730 #>>42167790 #
2. 6510 ◴[] No.42166679[source]
If there is a wrong way to do something someone will do it.
replies(1): >>42167211 #
3. hinkley ◴[] No.42167211[source]
There’s an old saying attributed to the Inuit: everyone enjoys the smell of their own farts.
4. marvinborner ◴[] No.42167412[source]
I think it's all right if you're used to the notation. The first two lines are tagged unions and will be recognisable as such if you're familiar with encodings like Scott/Church pairs/lists/numbers. Once you understand the structure, the definition of `bind` becomes obvious, as its two arguments represent the cases "is nothing" and "is just", where in the first case Nothing is returned, and in the second case the function is applied to the value inside the Just.

I think that writing such code, if only for educational purposes, can be really helpful in actually understanding how the state "flows" during the monadic bind/return. Typical monad instantiations of Maybe do not give such deep insight (at least to me).

> Just because you can do a thing doesn’t mean you should.

Of course you should, where would be the fun in that?

replies(3): >>42167560 #>>42167804 #>>42167828 #
5. salawat ◴[] No.42167560[source]
>I think it's all right if you're used to the notation.

Higher mathematics in a nutshell.

>Of course you should, where would be the fun in that?

Also higher mathematics in a nutshell.

Narrator asks: Who should we put in charge of <<thing that will effect people in a tangible way>>?

Not the mathematicians! echo the crowd in unanmity.

Narrator asks: Who will we delegate the task of <<abuse of notation>> to?

The crowd grumbles, arguing amongst themselves whether such a question even warrants an answer. A mathematician stands up, proclaiming "We'll take it!", following up with, "Once you understand the notation involved in my previous statement, you will understand why this outcome is inevitable."

The crowd, seeing the wisdom of not even embarking on that tribulation, assents to the delegation, given the task of undoing the abuse of notation for the legibility of the layperson is also delegated to the aspiring mathematician.

Scene opens on current day...

6. ◴[] No.42167730[source]
7. williamcotton ◴[] No.42167790[source]
It’s definitely easier to read in an ML language, that’s for sure!
8. tmtvl ◴[] No.42167804[source]
> The first two lines are tagged unions

Are they? But in the Nothing you have 2 identical members (`nothing' without arguments), won't that throw an exception?

To borrow Rust syntax (pun intended):

  enum Nothing {
    nothing,
    just
    nothing
  };
That's just weird.
replies(2): >>42167978 #>>42168288 #
9. IshKebab ◴[] No.42167828[source]
It's alright once you get used to it usually means it isn't alright in my experience. There are exceptions of course.
replies(1): >>42168178 #
10. marvinborner ◴[] No.42167978{3}[source]
When encoding tagged unions as lambdas, the tags are arguments. In this case `Nothing` has two available tags (`nothing` and `just`) and uses the tag `nothing`. `Just` does the same with the tag `just`, only that the tag gets an additional argument (as does its constructor `Just`), such that the value can be extracted afterwards - just like in an enum:

  enum Maybe<T> {
    Nothing,
    Just(T),
  }
11. fiddlerwoaroof ◴[] No.42168178{3}[source]
This is a big reason why legacy production code bases are such a nightmare to work with: developers refuse to learn anything beyond the minimum necessary to pile on yet another band-aid fix and the code base turns into a disorganized ball of mud
replies(1): >>42170479 #
12. ethbr1 ◴[] No.42170479{4}[source]
Alternative: successive developers each piled on their own, different coding preferences, leading to frankencode that requires keeping every paradigm at once in working memory