3 ms·
I have my share of gripes about Haskell (which I'm assuming is the language you have in mind when you're talking about a pure FP language), but even with the sa
by dwohnitmok 5y ago
I have my share of gripes about Haskell (which I'm assuming is the language you have in mind when you're talking about a pure FP language), but even with the sarcasm disclaimer, this is a pretty extreme strawman.
This is the equivalent Haskell.
turnOnThreeLEDs = for_ [1..3] (\i ->
do
LEDTurnOn
threadDelay (10^6)
LEDTurnOff
)
or all in one line
for_ [1..3] (\i -> do { LEDTurnOff; threadDelay (10^6); LEDTurnOff })
It looks basically the same.
EDIT: I would also strongly dispute the idea that FP is structured around flow instead of data structures. In fact I'd say that FP tries to reduce everything to data structures (this is most prominently found in the rhetoric in the Clojure community but it exists to varying degrees among all FP languages). Nor is SQL an FP language (the differences between logic programming a la Prolog and ultimately therefore SQL and FP is very very different).
FP's biggest drawback is that to really buy into it, you pretty much need a GC. That also puts an attendant performance cap on how fast your FP code can be. So if you really need blazing fast performance, you at least need some imperative core somewhere (although if you prefer to code in a mainly FP style, you can mainly get around this by structuring your app around a single mutable data structure and wrapping everything else in an FP layer around it).
- systemvoltage 5y agoWhat you wrote is imperative despite the fact that it’s written in Haskell.
- dwohnitmok 5y agoI mean if pure FP is enough to write imperative code as well then the distinction between the two doesn't seem all that important to me. What would be a non-imperative equivalent to illustrate your idea?
- Jensson 5y agoSmall examples of mutating state in Haskell are about as meaningful as small examples of pure functions in Java. Small examples are really easy to do and not that ugly, bigger more complex examples don't look so nice. The whole reason people want to use Haskell is because doing complex state mutations is horribly ugly and unergonomic so people don't do it, that is a feature of the language.
- TuringTest 5y agoSo, you recognize imperative is a subset of functional? :-P do-blocks have perfectly functional semantics, so if you consider that to be imperative as well, this means that a sequence of instructions changing state is both imperative and functional, as long as you declare where the state is being handled in your code. And yes, of course functional code can handle state. The good thing about this 'Haskell imperative' style is that it doesn't fall prey of side effects, the bane of imperative programs (uncontrolled side effects are NOT a good thing). In Haskell, you control why and where you allow them.
- jcelerier 5y agoOne could also make a language that has exactly the same visual syntax that C where ; is specified as a functional composition operator instead of a separation of instructions. These kind of mindgames are pointless - if your code is sequencing instructions, it's imperative ; if it's denoting it's functional
- TuringTest 5y agoIf you do that, then you have to admit different kinds of imperative code: C-imperative style that can modify any state in the application as side effects, and Haskell-imperative where you can only modify state explicitly declared as input to the procedure. It's not just mind games, the difference has very real implications to the architecture of the whole program and the control you can exert over unpredictable side errors.
- auggierose 5y agoWell, you DID sneak a monad in there :-)
- tromp 5y agoRather unavoidable when turnOnLED's likely type is IO () ...
- auggierose 5y agoRather unavoidable when you have types like IO() in the first place.
- tromp 5y agoUse of that type is easily limited in Haskell code. For instance, in my chess counting project [1] only a few lines in Main.hs use IO (), while the other approximately thousand lines of code have nothing to do with IO (). [1] https://github.com/tromp/ChessPositionRanking https://github.com/tromp/ChessPositionRanking
- mordae 5y agoSo what? The point is to make it easy to program imperatively (with effects, where relevant) while simultaneously reclaiming the ability to check for correctness and maintain laziness by default. What's so good about implicit sequential evaluation? Shouldn't the effect ordering be explicit? Isn't explicit better than implicit?
- auggierose 5y ago> Isn't explicit better than implicit? That's the point, isn't it. No, explicit is not always better than implicit.
- deleted 5y ago[deleted]
- PennRobotics 5y agoWithout knowing Haskell, it looks like there are bugs in the code. Specifically, there's no delay after LEDTurnOff in the first example, and you have the same function name twice in the second example. If those are bugs, I'd forgive that. If those AREN'T bugs, then keep me far, far away from FP! Also, what is the point of i? Clearly, each LED should have its own index, but then i is never used again. (I understand this could be pseudocode or there's a lot of other code not included.) And the ranges are inclusive in Haskell? I feel like a lot of friction between Matlab and Python involves how each language's indexing/slicing/ranges are represented, so it's interesting to see each language's approach (indenting like Python, lower camel case, delays in us, etc.) --- but with every language difference, I'm personally less inclined to want to learn something new without a great reason.
- dwohnitmok 5y agoAh yes you are totally right. I misread the initial example: turnOnThreeLEDs = for_ [1..3] (\led -> do turnOn led threadDelay (10^6) turnOff led ) It should be the above (i is changed to led), where I thought the original was automatically going to a new led and didn't realize that `led` was actually an integer and `turn_on` and `turn_off` are basically pseudo-methods (or extension methods). (The original code also only sleeps after turning an LED on, not off) Indeed the second example is a typo that should have on vs off. for_ [1..3] (\led -> do { turnOn led; threadDelay (10^6); turnOff led }) The joys of writing code on mobile and too much copy pasting. `i` is the same thing as `for i in...`. Also yes ranges are inclusive.
- PennRobotics 5y agoThanks for all the info. I want to give FP a proper try one day, and there are many different roads, but it's always a rocky start for me with a new language. Having a clear translation from one to the other is important, so I'm glad you updated this. True that this matches the original example. I guess my mind filled in the second delay automatically when it noticed, "this isn't gonna blink to the naked eye!"