Do those things come under the category of unsafe? Why would we be programming if it weren't to do those kinds of things? If I buy a shovel, at some point I'll probably want to dig a hole with it.
However, the goal of haskell (and indeed any language trying to be safe in the way SPJ means) is to be able to have most code be safe/effect-free, and then to have effects be very carefully controlled and limited in their use. Things like the IO monad mean many parts of haskell code can't do IO in fact.
We obviously do want some sort of effect in the end, but the idea is it's safer to contain those effects in very limited places, and not allow effects to happen literally anywhere at any time.
Note, unsafe in the SPJ video was specifically about effects, while "unsafe" in rust terminology is mostly about memory safety, so those two terms really aren't the same word, and to be honest that can make communication less clear. I don't know what "category of unsafe" meant in your comment really.
But in any case, yes those things I mentioned can fall under the category of "unsafe". In the category of memory safety, you want to be sure (with compiler guarantees!) that no thread will secretly free some allocated memory while you are still using it. This is something the borrow checker can give you in rust. There are no builtin guarantees in Rust that this fancy new library you imported won't do `DROP TABLE users`, or open a socket to https://haxorz.com and pass on all the environment variables. There are other languages in which you can be sure that a function cannot open any sockets unless it specifically has "can open sockets" encoded in its type.
In Haskell, a function like 'Int -> String' is safe (definitely not bad). A function like 'Int -> IO String' is unsafe (it might be bad; we hope not). If it were possible to specify "bad" via the type system (like the type of use-after-free) then we would want that to be a type error (like it is in Rust).
I don't think that's changing the use of language at all. For example, playing one round of russian roulette is 'unsafe'; even though (a) we don't know if it will have a bad outcome or not, and (b) the chance of a good outcome is much higher than that of a bad outcome.
foo :: Int -> String
foo x = seq
(unsafePerformIO $
println “pwned”)
(show x)https://downloads.haskell.org/~ghc/latest/docs/html/users_gu...
In practice that's true of Haskell as well.
Anyway, controlling side effects is really about avoiding accidental/unintentional side effects, i.e. mutating the world[1] by accident. Of course if everything is in IO, you only get "can do anything to the world" and "can't change the world at all", so Haskellers are usually interested in more fine-grained separation of effects than just pure/impure.
Of course, you are also trusting that code you're using doesn't do crazy unsafePerformIO, etc. stuff, but at least you can grep the code for that :). And sometimes unsafePerformIO can be a good thing to do 'magical' things which are referentially transparent but require mutation for asymptotics or performance generally.
[0] Safe Haskell is more about that kind of thing, but AFAIUI it isn't really in much use and never really took off. IIRC, it might even be slated for removal?
[1] Which is the ultimate shared mutable state, after all.
Haskell has a separate problem here: all of these can fail, and there's nothing in the type system to alert you of this (in the standard library), such failures just mindlessly throw exceptions like some Java monstrosity. In Rust, on the other hand, all such functions return something like Either Result Error, forcing the caller to check (and ideally handle) any errors. Not to mention async exceptions in Haskell, which can happen anywhere, and the fact that every value is really of type value|undefined, due to laziness. It's practically impossible to cleanly formally reason about code in Haskell due to the fact that anywhere could be interrupted by an async exception.
When even C++ is considering trying to remove exceptions from the standard library, Haskell's love for untyped exceptions everywhere is seriously behind the times for a language that prides itself on correctness.
> all of these can fail, and there's nothing in the type system to alert you of this (in the standard library), such failures just mindlessly throw exceptions like some Java monstrosity
There's `MonadThrow` in Control.Monad.Catch which hints that the monad in question can throw exceptions. Admittedly, partial functions like `undefined` and `error` are still usable...
> Not to mention async exceptions in Haskell, which can happen anywhere, [...] anywhere could be interrupted by an async exception
... and they can throw exceptions everywhere, just like asynchronous exceptions, but it's actually a strength! Haskell enforces a clean separation between impure code (typically in a monad) and pure code. You can only catch exceptions in the IO monad, which often lies outside of the core logic. Due to this unique strength, Haskell is one of the very few languages that can safely terminate running threads.
Impure code can become harder to write because of exceptions, but since you don't write everything in the IO monad, the problem is largely mitigated. Yes, exceptions are hard to get right, and that's exactly why other languages are trying to get rid of, but Haskell makes it quite tractable, (though still quite annoying). Rust used more Maybes and Eithers in the IO monad (to borrow jargons from Haskell), but it's also got panic, which is the actual Haskell exception counterpart.
> and the fact that every value is really of type value|undefined, due to laziness
To be pedantic, Haskell has levity polymorphism, which gives you unlifted datatypes, like in OCaml and Idris. Even older Haskell has unboxed datatypes that are not lifted.
> ...Haskell's love for untyped exceptions everywhere...
Nope, Haskell's exceptions are typed.
> Nope, Haskell's exceptions are typed.
logicchains means that the exceptions that a function can throw are not noted in its type (and as a massive Haskell fan I agree with him/her that that is very annoying).