While I agree that Haskell is a great language and everyone should learn it because it's fun to play with it, I think solution to author's problems (and as a current evolution step) would be something like Kotlin.
It's Java-like language (no need to manage pointers), and it doesn't have null-pointer problem, but it's still high-level imperative OOP language.
While many people say that they're code in Haskell is easier to read, since it has this "side-effect-free" guarantees, for me it seemed as not true for some time recently. In Haskell, when your code gets complicated (and starts to have some patterns you want to omit in typing), you start writing Monads. And when you start writing monads, your code gets harder to read since you need not only consider the code, but also keep (>>=) operator (all of them, if you use multiple monads combined via transformers) in your head for every pair of lines. Your code can suddenly have something like global variables (dynamic scoping) hidden in monad (as with State monad), it's flow can be changed dramatically and different other surprises.
could easily put 2 different values into `a` on each line. Of course, technically everything is still correct, and getA still returns same result for each call.
Yes. You're free to rename second a to b. The point I wanted to make is that it's the same getA, but anyone reading the code should understand that result binded to a and b will be different.
Depending on the monad. If you are in Reader and getA == ask, a and b will have the same value. If you are in IO and getA == getLine, a and b may be different.
The whole point I was talking about is that as soon as you're in monad, referential transparency becomes a bit a "lie", and a <- getA, b <- getA becomes non just analogous to a = getA(); b = getA();, but even worse in "referential transparency" sense.
Referential transparency is not a lie; getA is just a value. It could be substituted for its meaning without altering the program. For example, the following program:
foo = do
a <- getA
putStrLn ("Hello, " ++ a ++ "!")
where
getA = do putStrLn "What is your name?"
getLine
Is equivalent to:
bar = do
a <- do putStrLn "What is your name?"
getLine
putStrLn ("Hello, " ++ a ++ "!")
Yes, that's exactly what I was sayint 2 comments upper this thread:
> The point I wanted to make is that it's the same getA, but anyone reading the code should understand that result binded to a and b will be different.
So, while referrential transparency is still in place, programmer who reads the code will most likely care not about getA's result, but rather what will a and b get binded to, and in those terms it's just the same as good old
It's Java-like language (no need to manage pointers), and it doesn't have null-pointer problem, but it's still high-level imperative OOP language.
While many people say that they're code in Haskell is easier to read, since it has this "side-effect-free" guarantees, for me it seemed as not true for some time recently. In Haskell, when your code gets complicated (and starts to have some patterns you want to omit in typing), you start writing Monads. And when you start writing monads, your code gets harder to read since you need not only consider the code, but also keep (>>=) operator (all of them, if you use multiple monads combined via transformers) in your head for every pair of lines. Your code can suddenly have something like global variables (dynamic scoping) hidden in monad (as with State monad), it's flow can be changed dramatically and different other surprises.