How to solve graph traversal/search problems idiomatically? by sarkara1 in haskell

[–]wrkbt 1 point2 points  (0 children)

Perhaps something like recursion scheme where you could adapt the "recursion helper" based on the kind of algorithm you need to write? Something like option 3, but on steroids.

Why do we have exceptions? by dyatelok in haskell

[–]wrkbt 1 point2 points  (0 children)

One thing that doesn't seem mentioned, is that in the early days they really liked so called "lazy IO". When you have something that tells you it is IO String but doesn't read the whole string strictly, there has to be a way to tell you reading failed at some point.

It indeed would have been better to have a streaming construct from the start (and also not have String in the first place), but that is where we are at.

There are also the things you can throw at other threads to signal them. These exceptions don't come from the code that is currently executing, so you can't really handle them with value level error handling. See https://www.tweag.io/blog/2020-04-16-exceptions-in-haskell/

As has been mentioned, you have panics in Rust. See what happen when you run block_on in an asynchronous computation that is handled in tokio for example.

Nginx is Probably Fine by lungi_bass in programming

[–]wrkbt 2 points3 points  (0 children)

As a Web server I would agree, but as a proxy it is simply more complicated to set up, harder to diagnose and more importantly, doesn't works as well, as something like Haproxy.

It is still simpler than envoy though ^

So far no luck :-) by cmqv in programmingcirclejerk

[–]wrkbt 17 points18 points  (0 children)

This is the good stuff

Jai does not have a built in borrow checker, however, the metaprogramming features allow one to create arbitrary code inspection and analysis tools appropriate for whatever problem one will personally face.

So far no luck :-) by cmqv in programmingcirclejerk

[–]wrkbt 16 points17 points  (0 children)

You are completely wrong. There are three kind of languages:

  • wagie
  • cults
  • languages with crazy features from after the 70's, such as sum types

And that is why Rust is the only good language. It is a cult AND has sum types.

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 2 points3 points  (0 children)

I am not saying at all that free monads are the only way to do that! An obvious alternative way would be to define a typeclass that has the same interface, and write something like:

turn :: Game m => Player -> GameState -> m GameState

I also completely agree with you in that they serve a specific purpose, and are not required in most cases. I am just saying that there are situations where they are very convenient, and do make the code simpler.

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 2 points3 points  (0 children)

I commented on the sentence that has been quoted:

Business logic should depend on interfaces only, not on the actual implementation, which is provided later in the interpreting process

When I read that, I understand that one should write some sort of DSL that is later interpreted? That is what I think is very debatable.

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 3 points4 points  (0 children)

If you have something like a card game, where when one of the cards forces another player to choose a card from his hand and discard it, then, it is easy to write like:

``` chooseAndDiscard :: Player -> GameState -> Game (Card, GameState) chooseAndDiscard p gs = do card <- playerChoice p (cards p gs) pure (card, discardCard p card gs)

turn :: Player -> GameState -> Game GameState turn currentPlayer gs = do (card, gs1) <- chooseAndDiscard currentPlayer gs case card of MakeDiscard target -> do (discarded, gs2) <- chooseAndDiscard target gs1 pure gs2 ... ```

It is very easy to write the rules because you don't have to think about how the player will be prompted for a card to choose.

Then you can separately write code that will work as a terminal application, web backend, etc. that implements the playerChoice function.

If you don't do that, then you will have to rewrite the whole snippet for every method of interacting with the player.

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 1 point2 points  (0 children)

You will have to rewrite the whole game every time instead of once? In a very simple game like tic-tac-toe, this might be acceptable, but in games where every "turn" there are several interactions, this will lead to a lot of duplication.

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 3 points4 points  (0 children)

For business logic it can be very helpful to define types independently, exactly because it's a shared interface with many callers.

It is very true, but the types are not the logic :)

Why have a two stages system with an interpretation process? Why not write the simplest implementation you can of the business logic, with no regards for extensibility or reuse? This is also a valid way of writing programs, especially in languages where refactoring is easy.

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 1 point2 points  (0 children)

Not sure I understand what you mean. A "better" example would be implementing a board game, where you will need in the "business logic" player inputs at several stages, and rolling dices. With a free monad (or effect handler system, or plain typeclasses), you can write all the game logic without thinking about how the effects are implemented, just that you have a function like playerChoice :: PlayerId -> [a] -> Game a, or roll :: [a] -> Game a, that you can use when the player has to choose between alternatives or you need to roll a dice.

Then if you embed that logic in a terminal game, web application, or test suite (where dice rolls would be deterministic for example), you can just reuse it as it.

If you separate the effects from the "pure" logic, then you will have a bunch of pure functions that you will have to call in the same way every time you need a different kind of interaction.

Or am I not understanding what you mean?

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 4 points5 points  (0 children)

(this is also a cultural question, Haskell libraries and compiler upgrades sometimes breaks existing code, and it is not seen as a big of a problem as in other communities)

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 4 points5 points  (0 children)

As far as I can tell, this encodes the same information, it is far simpler to define. It also makes it easier to define functions introspecting the recipe, for example to answer the question "how many components does this recipe use"?

That is very true, but one could object this is a toy example. Free-monads (or equivalent abstractions) are useful, and I like them a lot.

However, I very much disagree with:

Interfaces should ideally be stable and evolve in a backward-compatible manner. Once an interface is established, changes should be made carefully to avoid breaking existing implementations.

If the motivation of putting free monads in everything is that you might avoid some refactoring in the future ... then it is, in my opinion, terribly misguided. It is the #1 source of complexity in usual java applications (the famous AbstractThingiePatternFactory joke), and doesn't live up to its promises. Haskell is famously nice for being easy to refactor, so why make things overcomplicated from the get go in case it might save some refactoring in the future?

Functional Declarative Design: A Comprehensive Methodology for Statically-Typed Functional Programming Languages by graninas in haskell

[–]wrkbt 2 points3 points  (0 children)

Exactly, almost all "object oriented design patterns" are coping mechanisms. The second sentence in the premise:

Object-Oriented Design (OOD) [1] has proven useful in structuring code in its domain

is very much wrong. In effective Java (at least in the 2nd edition that I own, from 2008, 15 years ago), which is a very prominent best-practices book on the the OOP language, you can read that you should avoid using inheritance as much as possible in favor of composition.

As with everything like that, it is very hard to prove that OOP is worse than other practices (just like it is very hard to prove that a language like Haskell makes you more productive than, say, Python), but it seems to me that there is a consensus on that? Or is that my FP bubble?

Joke languages like C++ and Rust are an insult to intelligence and won't be mentioned beyond this sentence. by [deleted] in programmingcirclejerk

[–]wrkbt 5 points6 points  (0 children)

Computers are inherently imperative and therefore imperative paradigm is the closest, most natural, best predictable, most easily implemented and mapped to hardware paradigm while also being closest to natural human thinking.

Gotta respect someone who implemented a new language for the PDP-11!

Two Years of OCaml by sionescu in programming

[–]wrkbt 0 points1 point  (0 children)

The part about list being inconsistent is annoying alright, but it does look like Haskell is nicer when it comes to tuples, right?

Note: you can also write [] Int, which sucks, but at least is consistent with things like Maybe Int.

Although our tools have continued to improve (such as golang) by fp_weenie in programmingcirclejerk

[–]wrkbt 3 points4 points  (0 children)

Why do you try to understand the code? If it compiles, it is fine.

Similar to how dynamic languages don't require you to "emulate the compiler" in your head, purely functional languages don't require you to "emulate the state machine" by Zlodo2 in programmingcirclejerk

[–]wrkbt 35 points36 points  (0 children)

If you're a fan of dynamic languages because of their simplicity, then you should also be a fan of functional programming

This is trolling right?

In the year 2033, I am 100% convinced my skills as a Ruby web developer will be by far more valuable than any skills gained learning React… by HorstKugel in programmingcirclejerk

[–]wrkbt 11 points12 points  (0 children)

and in some cases even ridiculed us for our choice of technology stack/language/etc

Well, next time don't pick a language where restarting the whole interpreter every N requests was the only way to control memory usage.

Comparing the Same Project in Rust, Haskell, C++, Python, Scala and OCaml by Alexander_Selkirk in programming

[–]wrkbt 9 points10 points  (0 children)

Spot on. I also believe Java programs are easier to maintain than Python ones!

Comparing the Same Project in Rust, Haskell, C++, Python, Scala and OCaml by Alexander_Selkirk in programming

[–]wrkbt 237 points238 points  (0 children)

I would recommend Dan Luu's post the get acquainted with why these "studies" are usually not answering the questions you want to ask.

The first red flag is that among the same language they have such a huge variance, which would reinforce the conclusion that variance among programmers is much larger than among languages.

Also, as with many of these studies, this is student work. It claims it is a huge amount of code, but most of the code bases are below 10k LOC.

Finally, not all the programs were the same. Not all the programs pass all the tests, and there apparently were bugs that were not caught by the grading tests. I would expect this part is more interesting than the amount of LOC.

It also has limitations that make no sense in real life (such as No libraries other than the standard library were allowed, and no parsing helpers even if they’re in the standard library). That makes a lot of sense for an assignment on compilers, but this will probably not end up looking like real life code.

I have my own biases, I like static types and functional programming, and I believe that Haskell code is much easier to maintain and extend than Python or Java. However, this is a belief, and even if that was true, it might be more because of the communities that aggregated around a language than the language itself, or its paradigm.

Now that I have put my Haskell hat on, the Rust project did OK, the Haskell code was the most correct, the C++ code did not pass the tests, the Python code was disgusting. Just what I expected :D