Earlier quoted context omitted.
With regard to declaring the lack of side effects in an interface, I'd just like to mention that C++ is very nice in this regard too, and I think it's an important feature of C++ that is often overlooked. Yes, it's true that with casting and so on you are not actually ensuring anything when you declare a function const like you are with Haskell, but you announce to other programmers who will use your code that: 1) Th…
D actually has a better model for pure functions than C++. See http://dlang.org/function.html#pure-functions
What's wrong with Object-Oriented Programming and Functional Programming
131–140 of 145 posts
Re: What's wrong with Object-Oriented Programming and Functional Programming
#132Use the tool that is apt for the job. Programming languages and paradigms are tools. Tools are not greater than end products - period.
Another part of me feels like that's saying "Don't fall in love with your future spouse".
Re: What's wrong with Object-Oriented Programming and Functional Programming
#133Earlier quoted context omitted.
The way Haskell manages side effects is inspired, and I don't think anyone can say that Haskell is not a beautiful and coherent language. I only dabbled in Haskell a bit so I may be wrong, but I think that the problem with the way it manages side effects is that it does so through lazy evaluation, and lazy evaluation is hard to wrap your head around. So I think that if there is one big problem with Haskell, it is thi…
> but I think that the problem with the way it manages side effects is that it does so through lazy evaluation. This is not so. > and lazy evaluation is hard to wrap your head around. technically haskell is non-strict, not lazy. (a + (b * c)) evaluates + then * instead of * then +. Also strictness annotations can change this behavior. > They require programmers to think and program solely within Haskell's lambda calc…
What do you mean by that?
> (a + (b * c)) evaluates + then * instead of * then +.
AIUI,
head 2 [1, 2, (digit_of_pi 1000000000) ]
is forbidden from calculating the billionth digit of pi. That's a pretty strict (play on words intended) kind of laziness, even if not the theoretically maximal definition.Re: What's wrong with Object-Oriented Programming and Functional Programming
#134Earlier quoted context omitted.
The way Haskell manages side effects is inspired, and I don't think anyone can say that Haskell is not a beautiful and coherent language. I only dabbled in Haskell a bit so I may be wrong, but I think that the problem with the way it manages side effects is that it does so through lazy evaluation, and lazy evaluation is hard to wrap your head around. So I think that if there is one big problem with Haskell, it is thi…
Dabbling really is not enough to show you the problems with your assumptions. You are right that there is a cost, but it is really paid once up-front by each programmer. I could have written this same comment five months ago, before I started down the long dark tunnel of doom which is to go beyond LYAH and trying to write a real application. I think it was two months before I saw a light at the end of that tunnel - a…
Monads sort of force you to make plumbing visible, and it's not so neat as a result. For example, consider a big program that has two modules. The module A calls module B to do something. Now later, you want to add logging to the application. In normal languages, you can just call logging functions (which do IO), from within module B; module A doesn't have to know a thing. In Haskell though, you have to wire the IO monad (or some other monad that does the logging and encompasses it) all the way from A to B. Or say, you want now to access database from module B. Again, you have to wire your DB access up from A, because that's where the entry point is.
In normal languages, plumbing like log access, configuration, DB access can be accessed from any place via global variables or singletons, without imposing a dependency on the main module (or other modules). In Haskell, it's like a military installation - every interaction with outside world has to go through main gate. I am not really sure if there is any benefit to it, but there is certainly a downside that the plumbing is becoming visible in Haskell.
If there would be way to declare something as "plumbing" and have it always available (but still explicitly declared as part of function signature), without having to pass it along everywhere, it would be great compromise, I think. It could even make the programs more type safe, because instead of passing RWS or IO monad everywhere, you could make functions dependent on just DB monad for database access, for instance.
Or you could then configure the plumbing for specific modules, something like dependency injection.
Maybe I am missing something, but I tried to find some articles about how to write large scale programs in Haskell, but no one really seems to explain this.
Re: What's wrong with Object-Oriented Programming and Functional Programming
#135Is there a blend between the two? I really like loops...
Let go of your loops and learn to map, flatMap, and fold! Once I really figured out how to use those effectively, I've written far few indexed for loops. I tried to explain this philosophy on a recent and unheralded SO answer: http://stackoverflow.com/questions/19720830/is-it-safe-to-mo...
Re: What's wrong with Object-Oriented Programming and Functional Programming
#136Earlier quoted context omitted.
Let go of your loops and learn to map, flatMap, and fold! Once I really figured out how to use those effectively, I've written far few indexed for loops. I tried to explain this philosophy on a recent and unheralded SO answer: http://stackoverflow.com/questions/19720830/is-it-safe-to-mo...
That looks sweet but I can't help but wonder: How are those implemented internally? It seems like it would be loops?
In actual languages, it depends. In languages without tail-call optimization [3] (i.e. Python and JS), a loop is probably the most efficient way. But with it, it's not particularly important. In a purely functional language, loops indexed by mutable variables aren't on the table, so you have to go the recursive route.
A basic flatmap on a list is pretty easy to define without for loops in JS (although I would definitely recommend just using a library for all sorts of practical concerns):
function flatMap(list, f) {
if (list.length) {
return f(list[0]).concat(flatMap(list.slice(1), f));
} else {
return [];
}
}
flatMap([1,2,3], function (x) { return [x, x]; });
// -> [1, 1, 2, 2, 3, 3]
[1] http://en.wikipedia.org/wiki/Lambda_calculus[2] http://en.wikipedia.org/wiki/Combinatory_logic#Combinatory_l...
Re: What's wrong with Object-Oriented Programming and Functional Programming
#137Earlier quoted context omitted.
Dabbling really is not enough to show you the problems with your assumptions. You are right that there is a cost, but it is really paid once up-front by each programmer. I could have written this same comment five months ago, before I started down the long dark tunnel of doom which is to go beyond LYAH and trying to write a real application. I think it was two months before I saw a light at the end of that tunnel - a…
I also started to study Haskell recently. In my view, it's great from mathematical perspective, but it has its problems. Monads sort of force you to make plumbing visible, and it's not so neat as a result. For example, consider a big program that has two modules. The module A calls module B to do something. Now later, you want to add logging to the application. In normal languages, you can just call logging functions…
I used to think that too, but if you have monadic code M and pure code P, if you need to tie P to M (say at a third callsite C), you just lift the P into the monad at C, and that's it. P stays pure, C of course gets monadic, but that is since it _is_ monadic.
Now logging: I guess people overpanic this. There are two separate sides of logging I think:
1) Effect logging: If you want to log effects (going to send the email, etc), you are already in IO, no worries.
2) App logic logging: This is more like debug-logging to verify that you logic works and flows as expected. If you need this in pure code, throw in a Writer monad for logging the stuff (can discard it if not needed).
2a) Eventually you'll get somewhere where you have IO, so you can dump the aggregated logs if you want.
2b) Or just use unsafePerformIO to send to a logging thread (beat me with a stick).
As a bonus, for app logging you might use a proper ADT for your log statements instead of string, which is great for testing, and even greater for persisting (in json, protobuf, whatever) and later inspection.
Re: What's wrong with Object-Oriented Programming and Functional Programming
#138Earlier quoted context omitted.
Yes, but when are they executed? When is the byte written to the file?
Well, you certainly can't start executing until the `IO a` thing has been evaluated, but there aren't any other constraints. Something that can confuse people (and I'm not sure if this is the case with you or not) is that an `IO a` may/probably will contain a closure. So evaluation and execution are interleaved, but not because of laziness.
Re: What's wrong with Object-Oriented Programming and Functional Programming
#139Earlier quoted context omitted.
Dabbling really is not enough to show you the problems with your assumptions. You are right that there is a cost, but it is really paid once up-front by each programmer. I could have written this same comment five months ago, before I started down the long dark tunnel of doom which is to go beyond LYAH and trying to write a real application. I think it was two months before I saw a light at the end of that tunnel - a…
I also started to study Haskell recently. In my view, it's great from mathematical perspective, but it has its problems. Monads sort of force you to make plumbing visible, and it's not so neat as a result. For example, consider a big program that has two modules. The module A calls module B to do something. Now later, you want to add logging to the application. In normal languages, you can just call logging functions…
Re: What's wrong with Object-Oriented Programming and Functional Programming
#140Earlier quoted context omitted.
&& and || are evaluated by first looking at the left operand, then at the right. That seems pretty strict to me. You're thinking of their short-circuit nature, that the right operand is not always evaluated; I believe that that is a different issue than strict vs. lazy.
Consider '||' as a normal function. Consider ||(f(x),g(x)). If this were strictly evaluated, we would compute f(x) and g(x), then pass them as arguments to ||. Instead, we compute f(x) pass it to ||, and compute g(x) only if it is needed. This is lazy evaluation.