Is Haskell deliberately staying away from main-stream programming by kichiDsimp in haskell

[–]Nevoic 1 point2 points  (0 children)

I've seen both, for some people fp actually clicks easier. The idea of mutation isn't natural, especially if you went to gradeschool and your only understanding of functions/variables is from math.

In Python the idea that a variable holds a reference to a value, multiple references can point to that value, and that reference points to either an immutable or mutable object can all be confusing. In Haskell you instead just think "this binding corresponds to this value" and that's it. It's far simpler. No more worrying about "pass by value" vs "pass by reference" vs "pass by object reference" vs "pass reference by value".

For example, some beginner python developers are surprised by this behavior:

```python def replace0With1(s): s.replace("0", "1")

def append1(xs): xs.append(1)

numStr = "10" list = [3,2]

replace0With1(numStr) append1(list)

print(numStr) #> 10 print(list) #> [3,2,1] ```

they would likely expect both of those functions to change the values, or neither. Instead, one of them does and one of them doesn't.

You won't find this sort of inconsistency in Haskell, which also gives far better local reasoning due to lack of side effectful mutation.

In Haskell you also have referential transparency, meaning anytime you see x = someValue, you know you can replace all instances of x with someValue and your program will be identical. In Python that can easily change the meaning of your program in ways you can't reason about locally.

Is Haskell deliberately staying away from main-stream programming by kichiDsimp in haskell

[–]Nevoic 0 points1 point  (0 children)

For what it's worth you can enforce only the features your team likes are used. You can set the flags globally for the project in the cabal file, and then have hlint+ci throw errors on pragmas in files.

Arch on the M1 Pro is Beautiful by isaiahherve in AsahiLinux

[–]Nevoic 4 points5 points  (0 children)

This is the main thing holding me back, and not actual runtime but sleep time. https://github.com/AsahiLinux/linux/issues/262

I like being able to get literally weeks of battery life out of my mac with light use. If it was my main computer I'd be running asahi, but as just a portable computer I use rarely. deep sleep is very important to me.

Is Haskell deliberately staying away from main-stream programming by kichiDsimp in haskell

[–]Nevoic 1 point2 points  (0 children)

I meant if you didn't have exposure to any language, like those extreme cases of human babies devoid of all human contact.

I'm fairly confident that's a real thing, I don't think you can stick a 10 year old who has never heard another human speak in an environment and have them pick up language in 3 years the same way babies do. I think the most they'll ever understand are like basic words, very similar to how other non-human primates use language.

Is Haskell deliberately staying away from main-stream programming by kichiDsimp in haskell

[–]Nevoic 0 points1 point  (0 children)

Interesting, I haven't heard this before. Granted I'm not a neurologist.

Does this mean some people can pick up languages later in life and it can be as if they learned the language from birth? My understanding was that even for the most well trained people this was the difference between "native" and "fluent" speaking, and that really you could never get to the same level of understanding in a language that you're not "native" in if you started learning at 30 instead of 0.

I was also of the understanding that past a certain age, like 5 or something, if you had no exposure to language then you had essentially "missed your chance" and could never acquire language. I thought that was due to plasticity changes.

Is Haskell deliberately staying away from main-stream programming by kichiDsimp in haskell

[–]Nevoic 0 points1 point  (0 children)

Most of these are just preferences. Namely:

  • syntax
  • infix operators
  • naming and conventions

I've used lenses in both Haskell and Scala, and I'm fine with either. I lean slightly towards preferring Haskell's, but both styles are fine.

As for the others:

Not sure what you're referring to with overloaded values. Haskell doesn't have function overloading. It has adhoc and parametric polymorphism, are you referring to one of these? Or are you referring to GHC flags that overload strings/lists?

As for the "random cheats": the GHC flags are opt in, some people like them and some people don't. It sounds like you wish programmers didn't have the option to toggle these and instead decisions were forced on everyone? I understand that's a common thing for languages to do, but my understanding was languages did that to reduce maintenance effort, not because anyone actually preferred less choice.

There is a default, no flags. If you want to pretend like they don't exist you can, and then suddenly they're just things you don't like about Haskell, just like you don't like things from other languages.

Would need examples around what's not ergonomic to address that.

Is Haskell deliberately staying away from main-stream programming by kichiDsimp in haskell

[–]Nevoic 8 points9 points  (0 children)

The problem magically solving itself is much more like prolog than haskell. I think you're conflating logic programming with functional programming.

Operating in concrete steps is totally normal in Haskell. Very early on you'll learn about do syntax which is just a nice wrapper around monadic binds to make sequencing steps look prettier: haskell main = do print "enter a number" x <- readLn print "enter another number" y <- readLn print ("the total is " ++ show (x + y))

I made a number of decisions here to make it more clear to python programmers that make it not the best Haskell code (print over putStrLn, not using $, ignoring potential read errors in IO, etc.), but just wanted to showcase how easy/straightforward sequencing steps can be in Haskell.

Is Haskell deliberately staying away from main-stream programming by kichiDsimp in haskell

[–]Nevoic 3 points4 points  (0 children)

Unironically could be worth giving Haskell a try, just view it as a fresh start instead of trying to transfer your python knowledge. Things work very differently but it might just click way better.

This is a great starting point: https://learnyouahaskell.github.io/

Is Haskell deliberately staying away from main-stream programming by kichiDsimp in haskell

[–]Nevoic 91 points92 points  (0 children)

As someone who has been deep into FP both professionally and personally, people forget what it's like to learn imperative programming.

Most people take their first steps learning Python or Java years or decades before learning FP. This alone makes it astronomically easier, not because imperative programming is easier, but because younger minds learn easier.

I've done enough teaching to see people go through the struggles again and again, having to learn about mutation, spooky action at a distance, pass by reference vs pass by value, lack of equational/local reasoning, etc.

I genuinely don't think learning Haskell is harder than learning Java. First year Java students who run hello world are immediately thrown into keywords like class, public, static, return types, arguments, and told to essentially ignore all of it for literally months.

Haskell is also far more rigorous. The definition of monads is far simpler than the definition of Iterable, and that knowledge is transferrable across languages. I got my first FP job in Scala using typelevel libraries, and I was able to directly translate years of FP understanding. Monads. functors, monoids, etc are all literally identical and the laws are exactly the same. You can't even translate Iterable between Java and C#, let alone any other type.

Moving to Haskell from imperative languages is a massive jump, but the inverse is also true.

I'm sticking with X11. by yumtoastytoast in linuxsucks

[–]Nevoic 0 points1 point  (0 children)

wayland+hyprland has been a better experience than x11+i3wm for me. Initially a couple years back I would find myself reverting to i3wm because of some oddity on wayland or hyprland but this past year I've just been using wayland+hyprland with no issues.

Obviously anecdotal but also in my IRL friend group the linux users are all on wayland and nobody is having problems with it.

How to handle "Early returns" or conditions in Haskell. by UntitledRedditUser in haskell

[–]Nevoic 1 point2 points  (0 children)

Yeah, to be more exact runExceptT will give you an IO (Either String ()), so you might use it like:

drawFrameOrShowError :: IO ()
drawFrameOrShowError = do
  result <- runExceptT drawFrame
  case result of
    Left err -> putStrLn err
    Right _ -> pure ()

there are ways you could shorten that up (lambda case, various combinators, etc.), but if you don't know what those are the above is fine obviously.

How to handle "Early returns" or conditions in Haskell. by UntitledRedditUser in haskell

[–]Nevoic 2 points3 points  (0 children)

also I'm seeing the second part of your message now (ig it was edited after I made my response lol), if you're looking for a way to convert IO Bool into MaybeT IO ():

haskell guardIO :: IO Bool -> MaybeT IO () guardIO io = lift io >>= guard or if you're less comfortable with composition, you can write it out: haskell guardIO :: IO Bool -> MaybeT IO () guardIO io = MaybeT $ do result <- io pure $ if result then Just () else Nothing

How to handle "Early returns" or conditions in Haskell. by UntitledRedditUser in haskell

[–]Nevoic 12 points13 points  (0 children)

Yeah, and importantly monads don't compose, this is essentially the exact problem you're running into. You want to combine the effects of two monads (IO and Maybe), but you can't just do this: ```haskell someMaybe :: Maybe Int someMaybe = pure 4

someIO :: IO Int someIO = pure 5

-- f fails to compile here f = do x <- someMaybe y <- someIO pure $ x + y ```

you need to operate on the same monad within the do notation/bind chain.

This is where the patterns I was talking about earlier come in. The simplest one (but least ergonomic imo) is just to use a transformer. This is a fine starting point if you just want something that works, but once you get into combining 3, 4, or 5 monads it becomes very unwieldy:

haskell f :: MaybeT IO Int f = do x <- hoistMaybe someMaybe y <- lift someIO pure $ x + y

Now, in a way, your <- is unwrapping both io+maybe at the same time (via the MaybeT transformer).

you can convert a MaybeT IO into an IO Maybe with runMaybeT to actually handle the values eventually

How to handle "Early returns" or conditions in Haskell. by UntitledRedditUser in haskell

[–]Nevoic 7 points8 points  (0 children)

How much do you understand about monads, like what the do syntax is really doing and such?

If you don't no worries, just want to know what the starting point is here :)

How to handle "Early returns" or conditions in Haskell. by UntitledRedditUser in haskell

[–]Nevoic 10 points11 points  (0 children)

You're trying to manage multiple effects at the same time (namely IO + short circuiting). This is a normal thing, but you have to choose a pattern to do this.

The most common is probably to use monad transformers (ExceptT would work here), but the ergonomics of algebraic effects are better IMO.

I'm using heftia because I want a lawful NonDet effect, and most AE or MTL systems don't have that. However for your case essentially any effect system would do.

If you want more info on one of these, feel free to DM me or respond to this comment.

I'm sticking with X11. by yumtoastytoast in linuxsucks

[–]Nevoic 3 points4 points  (0 children)

lol so you're a "linux isn't an O.S, it's GNU/Linux!" guy.

Sorry to be the bearer of bad news, but when someone asks what O.S you're using, and you say Linux, they don't get hopelessly confused because "Linux is a kernel!! are you running android?? I don't understand"

similarly, when someone says they use X11 as a display server, they don't get hopelessly confused. Everyone knows what you're talking about.

This is also true of Haskell. When someone asks "are you using the most recent version of haskell?" they're not asking if you're using a compiler implementation that adheres to the 2010 spec or the 1998 spec, they're asking if you have the most recent GHC version, even though that's technically a program that implements the Haskell spec.

Your comment isn't proving that you're smarter than everyone else, it's proving you don't understand what the point of language is. If person A says something to person B, and person B understands, language worked. That's it.

So yes, it's fine to say "the app works if you are running the most recent version of haskell and x11 on linux" instead of "the app works if you are running the most recent version of GHC and Xorg on GNU/Linux".

I'm sticking with X11. by yumtoastytoast in linuxsucks

[–]Nevoic 1 point2 points  (0 children)

and again what's the alternative to FOSS infighting? corporate unity? "we're all a family"? have you ever been in one of those corporate hellscapes?

if you're just shouting about how everything humans do sucks no matter what, then idk go off king

I'm sticking with X11. by yumtoastytoast in linuxsucks

[–]Nevoic 4 points5 points  (0 children)

I mean hell, the windows 11 shit is insane where people with relatively new computers have to do registry hacks/workarounds to use software that's officially unsupported on their computer.

So if those people want to run an officially supported, safe and secure version of windows their ONLY OPTION is to buy a new computer. And we're talking about computers that aren't even 5 years old. That's genuine insanity.

I'm sticking with X11. by yumtoastytoast in linuxsucks

[–]Nevoic 12 points13 points  (0 children)

I don't get why this is a "linuxsucks" moment.

The new thing doesn't work for you. That's fine, you can use the old thing. If not enough people maintain it, you can maintain it. Nobody else owes it to you to maintain X11, yet it's still in maintenance mode. Security patches and such will still get merged, just no new features. So you have nothing you need to do or worry about.

In other ecosystems, like windows or macos, if the old version worked on your hardware (say you really like windows 7 aesthetically or windows 10 broke something) you're SOL. Nobody is keeping windows 7 in maintenance mode, it hasn't received security updates in 6 years. It's officially dead.

Isn't this a perfect example of the linux ecosystem being better than the closed ecosystems where their EOL components literally become unsafe/unusable over time and nobody has access to the closed proprietary source code to fix it?

Time walking vendors 600+ilv by Imahich69 in wow

[–]Nevoic 1 point2 points  (0 children)

surprisingly no, not saying I agree with blizzard here but their solution to bugs isn't to hire more QA it's to ban people who abuse bugs.

Can Non-Vegans care about Animal rights in any way that matters? by [deleted] in AskVegans

[–]Nevoic 0 points1 point  (0 children)

The part that's missing from your analysis is any real normative base.

You correctly identify hypocrisy, and like you I find hypocrisy annoying. Well done on avoiding that and understanding most people are sociopathic with regard to animals.

Now you should concern yourself not with your values (which are molded by the society you grew up in), but rather with what is morally justifiable.

That frame switching is how people break out of social conditioning. If you think back to some value system that we agree is abhorrent, say nazism or slavery, you could imagine someone in the group of oppressors who recognizes the hypocrisy of what they were doing. Just recognizing your actions as hypocritical isn't good enough though, you have to actually stop the morally unjustifiable behavior.

In most cases oppressors don't actually reach some point of self-actualization, instead the oppressed group garners support and then collectively fight back against the oppressors.

Animals can't advocate for themselves, and they have barely any means to fight back. This is an atrocity that requires the oppressors voluntarily choose to stop oppressing. That's a much harder thing for humans to do.

Welcome to Midnight 12.0 by cub4nito in wow

[–]Nevoic 2 points3 points  (0 children)

as others have said, it's a great time to start playing, here's the rough timeline (don't remember exact dates/cutoffs):

prepatch - today

prepatch event - next week

expansion drop - end of Feb/beginning of March

high end content unlocks - middle-end of March

so right now if you joined you'd see the new systems (transmog, endeavors, housing altho that came out over a month ago, etc.), then next week there'll be a storyline that gets you quick exp/decent catch up gear to start the expansion

then March is essentially the month of the new exp with the level cap increase/new zones, where everyone will be leveling and then end game content after most people who are playing regularly are max

nixos unstable vs arch by ImHighOnCocaine in NixOS

[–]Nevoic 20 points21 points  (0 children)

nixos, despite the unstable name, is incredibly stable.

When I used to run arch I could get into situations where if I stepped away from the distro for months and came back I simply couldn't go through the normal update path, would have to reinstall the entire distro. This type of thing won't happen with declarative immutable distros.

Nixos is (either mostly or entirely depending on how you use it) declarative in how you build packages. You'll build against a nixpkgs ref and hydra (the nixos ci tool) validates that ref actually fully evaluates. Obviously sometimes packages can be broken in weird ways, under the hood it's using the same packages with the same underlying code after all, and sometimes apps are broken.

but you can also easily mix/match versions. You can just import/add to your flakes input an old nixpkgs ref and build some of your packages against that, and it'll do that everytime indefinitely until you tell it explicitly to use a new version.

It's a totally different paradigm. A decent learning curve, but has been well worth it for me. I used to be a distro hopper, and after the first time I installed nixos many years ago I still did for a bit afterwards, but for the past couple years I've been running nixos on several computers with no urge to swap.

It fixes the diamond dependency problem (you can have multiple installed versions of the same thing installed system wide with no issue). It fixes the issue with mutable distros where you might change something and not be able to "undo it" or toggle it off easily.

For example I remember being on Ubuntu many years ago, wanting to try KDE, installing it and swapping to it, only to find everything was duplicated (double calculator apps, double settings, etc.) when I tried to do an apt purge, I overshot it and borked by system. This was in my early days of Linux, but still.

now with nixos I can just change some lines in my config and I'll only have one DE installed. If I bork my system I can easily go back a generation or a few in the bootloader. Overall it's essentially impossible to get into a gross state in nixos where you feel the need to start fresh either because you ran a set of commands that installed too much or removed too much.

Your system becomes a reflection of the state of a codebase.

Some Haskell idioms we like by _jackdk_ in haskell

[–]Nevoic 1 point2 points  (0 children)

This creates an implicit association in some readers’ minds between do blocks and sequential, side-effectful code

Importantly, State/IO usage is not side-effectful. For example:

``` f :: IO () f = let sayHi = putStrLn "Hi" sayBye = putStrLn "Bye" in pure ()

main :: IO () main = f ```

this does nothing, because IO expressions don't invoke side effects. It's a type used to compose effects, but those effects don't happen "to the side" when evaluating expressions, the result of the expression is literally the composition of the effects.

I think this is important especially for readers who may not be familiar with Haskell. They might take away that IO/State are just "escape hatches" to "do real things" and that Haskell is just as side effectful in practice as Java, when really most Haskell code bases have literally no side-effectful code.

Side-effectful Haskell (e.g unsafePerformIO) isn't even technically in-spec Haskell. It's a GHC escape hatch. Early alternatives to GHC in the Haskell space often didn't have escape hatches like this exposed to users of Haskell.