These mean different things. In the former, an Event has to be able to hold any a, and that doesn't really make sense (unless I'm misinterpreting something) because the only value that inhabits all types a is undefined/bottom.
Or is that what you want? Is there a reason why you use higher-rank types (which make my brain hurt, require a lot of language extensions, etc.) rather than parameterized types? If so, could you spell that out?
Another example is this:
data EventF = forall m b c. EventF (b → Transient m c)
Again, I'm not really familiar with what you're doing so it's quite possible that using higher-rank types is exactly what you want (see: ST Monad and Lenses, where rank-2 types are crucial). I'm just having a hard time seeing it.
In the case of events, it is because I later have to store different event types in a List
so I define the list as [Event] . That is the container that feed the monad with events.
If I define Event as you suggest, I would need a existential type anyway.
data Event a = Event EvType a
data ListEvents= forall a.[Event a]
In the case of the continuations, I need to use a state monad that store this EventF data And I need to "erase" in some way the types to allow it to store them all for all events, no matter wich a and b they produce. I know that if in
x :: IO a
f :: a -> m b
If within the monad definition I store f (the rest of the computation) in the state monad, the type of this continuation when executed will be (m b) and it accept values of type `a` so I can coerce the continuation to this type even if I "erased" it when i put it in the state monad.
Anyway this approach has some problems that I solved in the second part
I realised that it was the main module that needed to be run, after switching to this module (I also deleted some things causing syntax errors in base.hs) and selecting it as the build target the example worked as expected. I think it's because I'm not so familiar with fpcomplete.
"Object-oriented programming" is like "God" or "feminism"-- pointless to debate until you define terms, and ranging from the agreeable/probable to the ridiculous depending on precisely how terms are defined.
The original idea was that, when a piece of software becomes complex, it should be factored out and given a simpler interface. Alan Kay used the cell as a metaphor: it's a complex machine that interacts with the rest of the body using a simpler language of chemical and electrical signals. And that turned out to be such a good idea that you see it even in non-OOP programming tools. Haskell's type classes are a comparable idea. FP picks the best noun (immutable data) and verb (referentially transparent function) for most purposes (of course, the world is stateful and there's some debate over how to manage that). At scale, we also have to deal with the "adjective problem" because we want to be able to code against abstractions rather than (less stable) implementations.
For example, it's a good thing that languages support a File object (an abstraction that Unix is built on) that allows application programmers to avoid having to know what kind of "file" they are dealing with. It's nice being able to use the same language (open/read/write/close) regardless of the physical machinery that the file lives on.
The problem is that corporate OOP has become complexity for it's own sake. Alan Kay wasn't saying, "Go out and design massive, complicated objects". He was only proposing strategies for when complexity became inevitable. Unfortunately, Business OOP (a bastardization of OOP, which had some good ideas at its core) rewards complexity, and you have "enterprise architects" who can't code but are paid to generate massive tangles of lines and boxes.
I think the blessing and the curse of OOP is that is actually pretty good for simulation (SIMULA got it right I guess :) ), so what you usually have is a program that's a simulation of a process. Even the standard OO modelling techniques encourage simulation of "real world" entities. But that direction doesn't lead to the most efficient,composable , or easy to reason abstractions.
It doesn't help that the main abstraction mechanism in OO (superclass/subtyping) is problematic enough that even most people recommend moderation in its use.
The actual big thing about computers (Turing Machines) is that they let us simulate things, including other computers. But, once we recognize the fact that some computers are “better” than others, we then realize that the amazing thing about computers is that they allow us simulate better computers, it's just hard to do so.
Thus, the blessing and curse of OOP, respectively, is that it’s ideal for building simulations (the actual point of computers), but also makes it really easy to simulate a worse computer on top of better ones. So, the real tragedy of “Enterprise” OOP is that it basically encourages programmers to first simulate lame computers (e.g. by building frameworks), and then write programs for them.
It's hardly any kind of "mess". It's the most practical and intuitive to reason about choice for a significant amount of work that needs to be done. FP excels at some cases but not all of them. Contorting all of my OOP code into a functional structure would be a nightmare.
Upvoted, though I disagree, because I hate when people use downvotes for quality content they disagree with, and you don't deserve to be grayed out.
"Object" often means "thing of which I have incomplete knowledge". When you have an Object, you've given up on reasoning about it from axiomatic principles or deep knowledge, and you're looking at it holistically alone.
Sometimes, that's just fine. The Unix File concept is a well-designed object, because you can use the read and write system calls without having to know whether it's a regular file, a socket, a tape drive, a memfile, or something else.
While working under incomplete knowledge is sometimes necessary, it's never the ideal. You can use Alan Kay's original OOP principles when software reaches a certain level of complexity, but shouldn't orient your programming around incomplete knowledge or unmanageable complexity. The problem with corporate OOP is that it enables the imprecision-of-thought of technically incompetent software managers and "enterprise architects" who are better at managing up than at solving technical problems.
In fact, Dijkstra spells out the problem with corporate OOP in two words, as quoted in the OP: complexity sells. Complexity + imprecision-of-thought = disaster. And a major reason why top-5% programmers love Haskell is because it simply blocks the imprecision of thought that characterizes typical, business-as-usual, mediocre corporate software development.
Well though. I agree with that. The good abstraction is more about interfaces rather than objects. I complain more about the primitive use of objects as message receivers" with state. That was at the moment the best solution available for the problem of managing events. But this idea of inversion of control pervaded all the industry in perverse ways Even where it was not necessary. The corporate OOP is mostly a consequence of that.
This is just random thoughts and there is much more to say. Neither I pretend to tell that OOP is wrong. What I say in the article is that the deconstruction of the recipe that OOP naturally demand is very painful and has too many drawbacks, and can be avoided with the right tools.
I think that there are objective measures of complexity. So there are objective measures of simplicity.
ideographic writing is more complex and less composable than phonetic writing and yet can express the same ideas.
Subjectively, a chinese can understand Chinese ideograms while maybe he find written English difficult to understand. But a Chinese would learn phonetic writing in less time than ideographic writing and would be capable to express complex ideas using the most composable writing system in less time, no doubt.
This article assumes too much background -- not of Haskell but of the authors prior work. It starts off: "I have a problem: How I present the few applicative and monadic combinators that I just developed."
Ummm ... which combinators? At least provide a link to the prior article that I assume introduced them. As introductions go, this article's introduction doesn't do a very good job.
You're right, he does link to the article (at least I think it's the one that is being referred to), but not until "Enter the monad" which seems later than it shoud be. Here is the link:
I see a lot of higher-rank types, like this:
as opposed to: These mean different things. In the former, an Event has to be able to hold any a, and that doesn't really make sense (unless I'm misinterpreting something) because the only value that inhabits all types a is undefined/bottom.Or is that what you want? Is there a reason why you use higher-rank types (which make my brain hurt, require a lot of language extensions, etc.) rather than parameterized types? If so, could you spell that out?
Another example is this:
Again, I'm not really familiar with what you're doing so it's quite possible that using higher-rank types is exactly what you want (see: ST Monad and Lenses, where rank-2 types are crucial). I'm just having a hard time seeing it.Thanks!