top | item 42303404

(no title)

bhargav | 1 year ago

Maybe because I haven’t used languages like these in the past, but I hardly think this is elegant, much read readale. I would hate my life trying to parse code like this in a 10k LOC codebase.

strSum = sum . map read . words

discuss

order

fleshmonad|1 year ago

It's actually very readable once you get the hang of it. The transition from imperative paradigms to Haskell can be tough, but once you've overcome this barrier, the code reads effortlessly. In your example case: split the string into a list of words, that is tokenize based on spaces. Then map the read function onto this, which will parse each of the "words" in the list into some type. Annotations would likely be needed here. Then sum this list.

I much prefer this over 10 levels of class indirections or procedural style.

brabel|1 year ago

Isn't it the case that anything is very readable once you get the hang of it? I think the problem is exactly in the "get the hang of it" part. For some languages, that's really difficult, while for others it's almost trivial. From my own experience, Haskell is very very difficult to "get the hang of" despite my multiple attempts, while something like Javascript is trivial for me (interestingly enough, except when it uses too much of the new FP patterns!) even when I do not program on it daily.

instig007|1 year ago

> In your example case: split the string into a list of words, that is tokenize based on spaces.

You've made a common mistake. You're wiring your listener's thinking with the imperative inside-out approach that you're used to. Instead, it should be explained as this: "strSum = sum . map read . words" is "a sum of all parsed values of the original input of space-separated words". The reason you should avoid inside-out explanations is because in Haskell you're allowed to move from general ideas to specifics, and you can sprinkle `undefined` and `_` for specific details whilst thinking about general ideas and interfaces.

HdS84|1 year ago

I really like the FP paradigm, but could you all stop using weird abbreviations and random characters as substitute for operations?

You don't do programming with chalk on a wallboard, for crying out loud. Ideally, you are using a good IDE with syntax completion. Therefore, readability matters more than the ability to bang out commands in as few keystrokes as possible.

djur|1 year ago

If you're familiar with Haskell, this is something you can just look at and parse without thinking. It's all basic Haskell syntax and concepts (function composition and partial application). I haven't touched Haskell for a few years and I didn't have any trouble interpreting it as "strSum is a function that takes a single string argument, splits it by whitespace, interprets each chunk as a number, and returns the sum".

devjab|1 year ago

I’m not familiar with Haskell and I could read almost all of that from it. No idea how you can tell it splits on white space though.

Symmetry|1 year ago

Compare it to a bashism like

  find . -name '*.py' | sed 's/.*/"&"/' | xargs  wc -l
But instead of using | to tie the different functions together you're using . and the order is reversed.

runeks|1 year ago

> Maybe because I haven’t used languages like these in the past [...]

Yes, that definitely the case.

If you know what each function above does, including the function composition dot (.), then this is like reading English — assuming you know how to read English.

bhargav|1 year ago

The “map read” part is what’s off. I think it’s because parens are optional or not required.

There are other languages which are functional as well. like the one in the article and like Elixir where readability is it sacrificed.

I still think readability is atrocious in this language. Sure I can get used to it, but I’d never want to subject myself to that

59nadir|1 year ago

In our codebase we enforced usage of `>>>` instead, which composes forward instead of backwards:

    strSum = words >>> map read >>> sum
For most people this then becomes "Apply `words` to the input argument, pass the result to `map read` and then `sum` the results of that".

I don't think `.` is super complex to read and parse, but we had people new to Haskell so I thought it prudent to start them off just with `>>>` and keep it that way. Most things are read left-to-right and top-to-bottom in a codebase otherwise so I don't see why not.

Edit:

I also told everyone it's fine to just spell out your arguments:

    stringSum sentence =
        sentence
        & words
        & map read
        & sum
In the example above `&` is just your average pipe-operator. Not currying when you don't have to is also fine, and will actually improve performance in certain scenarios.

Edit 2:

The truth is that there are way more important things to talk about in a production code base than currying, and people not using currying very much wouldn't be an issue; but they'll have to understand different pointer/reference types, the `ReaderT` monad (transformer), etc., and how a `ReaderT env IO` stack works and why it's going to be better than whatever nonsense theoretical stack with many layers and transformers that can be thought up. Once you've taught them `ReaderT env IO` and pointer types (maybe including `TVar`s) you're up and running and can write pretty sophisticated multi-threaded, safe production code.

solomonb|1 year ago

In a production application you generally don't write code like that. I find it tends to be the opposite problem where you often see giant `do` blocks performing all sorts of monadic effects.

djur|1 year ago

You especially wouldn't use `read`.

elbear|1 year ago

You can see it as a pipeline where the output of the right-most function is plugged into the input of the function to its left.

epgui|1 year ago

It’s not inelegant, it’s just unfamiliar to you.

worksonmymach|1 year ago

1. Change . to |

2. Reverse

Now you have:

words | map read | sum

Or..

$ cat words | map -e read | sum

bhargav|1 year ago

Yes but the notation of dot, plus such function names plus optional parens makes it sure read like English. That’s great but it’ll be a nightmare when you are also dealing with strings which similar English in it.

kreyenborgi|1 year ago

|> is a common way of writing the pipe in haskell, so

     words |> map read |> sum
IHP uses it a lot.

tromp|1 year ago

Would you propose the same change for nested function calls y = f(g(h(x))), changing it into y = x | h | g | f ?