
...In the tradition of the "letters of an ignorant newbie"... What's the consensus on the OOP in Haskell *now*? There're some libraries such as OOHaskell, O'Haskell, and Haskell~98's own qualified type system with inheritance. If I have GHC, which way to do anything OOP-like is considered "right" today? Cheers, Alexy

deliverable:
...In the tradition of the "letters of an ignorant newbie"...
What's the consensus on the OOP in Haskell *now*? There're some libraries such as OOHaskell, O'Haskell, and Haskell~98's own qualified type system with inheritance.
If I have GHC, which way to do anything OOP-like is considered "right" today?
Using existentials and typeclasses to do some OO things wouldn't be considered unidiomatic (particularly, using existentials to package up interfaces to values). In general though, using a functional approach will produce better (simpler) Haskell code, and make it more likely others will understand it. Personally, I run in fear from OO Haskell ;) Concrete examples of when you think you need an OO feature might be useful, so people can discuss the more FP solutions to the same problem. Cheers, Don

Well, I'm thinking in terms of OOD/OOA/OOP -- Design, Architecture,
Programming. That's about the only way to model a bog system. Say I
have a stock market model -- I'll have a database of tickers, a
simulator to backtest things, a trading strategy, etc.
Do Haskell modules provide enough encapsulation to design a system in
terms of them? What are the design/architecture units in Haskell if
not OO-based?
Cheers,
Alexy
On 1/27/07, Donald Bruce Stewart
deliverable:
...In the tradition of the "letters of an ignorant newbie"...
What's the consensus on the OOP in Haskell *now*? There're some libraries such as OOHaskell, O'Haskell, and Haskell~98's own qualified type system with inheritance.
If I have GHC, which way to do anything OOP-like is considered "right" today?
Using existentials and typeclasses to do some OO things wouldn't be considered unidiomatic (particularly, using existentials to package up interfaces to values).
In general though, using a functional approach will produce better (simpler) Haskell code, and make it more likely others will understand it. Personally, I run in fear from OO Haskell ;)
Concrete examples of when you think you need an OO feature might be useful, so people can discuss the more FP solutions to the same problem.
Cheers, Don

Alexy Khrabrov wrote:
Well, I'm thinking in terms of OOD/OOA/OOP -- Design, Architecture, Programming. That's about the only way to model a bog system. Say I have a stock market model -- I'll have a database of tickers, a simulator to backtest things, a trading strategy, etc.
Do Haskell modules provide enough encapsulation to design a system in terms of them? What are the design/architecture units in Haskell if not OO-based?
Design of functional programs is very bottom-up. The general plan is to identify the primitives for your domain and embed them in the language, then solve your problems using those primitives. Evolving your primitives and program concurrently as you get a better understanding of the problem/solution. A good intro to this kind of programming is 'On Lisp' by Paul Graham (http://www.paulgraham.com/onlisp.html). Of course, he is using Lisp instead of Haskell so many of the concrete techniques for implementing this method are different[*]. However, the first section of the book that talks about how you build something "on Lisp" is equally applicable to building software "on Haskell". I expect that in your domain, the primitives are things like: currency, time series data, trades, strategies, and so on. The primitive operations would let you "perform a trade", "back-test a strategy" and so on. Since it is close to your chosen domain, I highly recommend you look at http://research.microsoft.com/~simonpj/Papers/financial-contracts/contracts-... [*] On Lisp makes heavy use of macros in Lisp, which have no analog in Haskell, but can usually be substituted for lazy-evaluation and/or monads -- Alan Falloon

Hello Al, Tuesday, January 30, 2007, 6:01:16 PM, you wrote:
Design of functional programs is very bottom-up. The general plan is to identify the primitives for your domain and embed them in the language,
oh, really? may be i'm using Haskell in OOP way? :) i strongly prefer to use top-down style for application programming - i.e. i solve problem introducing auxiliary functions, then fill up these functions and so on recursively i use bottom-up style for library development, though, adding more and more higher-level functionality as library evolves -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Bulat Ziganshin wrote:
Hello Al,
Tuesday, January 30, 2007, 6:01:16 PM, you wrote:
Design of functional programs is very bottom-up. The general plan is to identify the primitives for your domain and embed them in the language,
oh, really? may be i'm using Haskell in OOP way? :)
i strongly prefer to use top-down style for application programming - i.e. i solve problem introducing auxiliary functions, then fill up these functions and so on recursively
i use bottom-up style for library development, though, adding more and more higher-level functionality as library evolves
The method I use is actually more of a "meet-in-the-middle". Its hard to know what your primitives are unless you know what you are trying to do. I find that the best approach is to try and write my program using whatever constructs feel natural for the domain, then see if I can define the domain constructs starting with the smallest, most obvious ones and combining them into the more complex nuanced constructs needed to solve my actual problem. Usually some tweaking is required to get a nice fit. Writing usable software is more craft than science. The OOP community has contributed a lot to the craft of programming. There are many concepts that have been refined by them that IMHO can be applied more easily in a functional style. IMO the major driving principle of good software design (OO, FP, or otherwise) is Once-And-Only-Once (http://c2.com/ppr/wiki/WikiPagesAboutRefactoring/OnceAndOnlyOnce.html). If you stick to OAOO, then no matter where you start you tend to converge toward a good solution(*). (*) However, depending on where you start OAOO does not always give the same good solution. I find that interesting. To me that implies that the solutions from different approaches form a Pereto optimal set (http://en.wikipedia.org/wiki/Pareto_efficiency) of the possible solutions, and that each approach buys you some sort of advantage at the expense of another. -- Alan Falloon

Donald Bruce Stewart wrote:
deliverable:
...In the tradition of the "letters of an ignorant newbie"...
What's the consensus on the OOP in Haskell *now*? There're some libraries such as OOHaskell, O'Haskell, and Haskell~98's own qualified type system with inheritance.
If I have GHC, which way to do anything OOP-like is considered "right" today?
Using existentials and typeclasses to do some OO things wouldn't be considered unidiomatic (particularly, using existentials to package up interfaces to values).
In general though, using a functional approach will produce better (simpler) Haskell code, and make it more likely others will understand it. Personally, I run in fear from OO Haskell ;)
Instead of OOP, Haskell uses (parametric) polymorphism which is more powerful than OOP. For instance, the function length :: [a] -> Int or, with an explicit forall length :: forall a . [a] -> Int counts the number of elements in a list "[a]", regardless of what type "a" those elements have. Moreover, it is guaranteed that "length" does not inspect or change the elements, because it must work for all types "a" the same way (this is called "parametricity"). Another example is map :: (a -> b) -> [a] -> [b] which maps a function over all elements in the list. In addition, Haskell has type classes (which are similar to "interfaces" in OOP). The most basic example is class Eq a where (==) :: a -> a -> Bool Thus, you have an equality test available on all types that are instances of this class. For example, you can test whether two Strings are equal, because String is an instance of Eq. More generally, you say whether two lists are equal if you know how to test elements for equality: instance Eq a => Eq [a] where [] == [] = True (x:xs) == (y:ys) = (x == y) && (xs == ys) _ == _ = False The important thing I want to point out in this post is that parametric polymorphism is indeed more powerful than OOP: already a concept like Eq is impossible to implement in OOP. The problem is best illustrated with the class Ord (*), which provides an ordering relation. Let's concentrate on the "smaller than" function (<) :: Ord a => a -> a -> Bool Can I create an interface that expresses the same thing? public interface Comparable { boolean smaller_than(?? y); } No, because there is no type I can attribute to the second argument of "smaller_than". The problem is that I can only compare to values of the *same* type, i.e. the type which implements the interface. Can I create a class the expresses the same thing? public class Comparable { boolean smaller_than(Comparable y); } This seems like a solution, but it is not. The problem is subtyping: if i make integers and strings members of this class, i would be able to compare the number 1 against the string "hello", which should be reported as a type error. I have no formal proof, but I think that the "<" function cannot be expressed in a type correct way in OOP. AFAIK, only Java Generics can express the requirement we want: interface Ord<A> { boolean smaller_than(A x, A y); } class String implements Ord<String> { ... } But Generics are a considerable extension to OOP. In fact, there is nothing really object oriented in here anymore, we're just on our way to parametric polymorphism. My final remark is about what this means for the existential quantifier in Haskell. Because of the injection inject :: forall a . a -> (exists a . a) the existential quantifier can be thought of as implementing some form of subtyping, i.e. (exists a . a) is a supertype of every a. The point now is: given type ExistsOrd = exists a . Ord a => a there is *no* instance Ord ExistsOrd where ... because we could compare arbitrary subtypes of ExistsOrd then. In the end, the existental quantifier has limited use for data abstraction, it's "forall" that makes things happen. Regards, apfelmus (*) We don't consider Eq because given a test on type equality, we can generalize the signature of (==) (==) :: (Eq a, Eq b) => a -> b -> Bool Indeed, this is what OOP equality does.

Well, it depends what you mean by OO. In a proper OO system, equality
means not just are these two things in the same state, but do they
refer to a single object. Invoking behavior on one will affect the
other, and the equality relation will still hold.
There are three properties that entities have in a OO model:
1 Identity
2 State
3 Behavior
objects are not values. Values don't have identity. This 7 is the same
as that 7, with no way of distinguishing them. They also don't have
state.You don't add 1 to 7 and turn it into 8 (unless you're in a very
old FORTRAN, where constants weren't). The result is a new value.
Values also don't do things. Functions map values to new values.
Of course, when most people are looking for OO, they're looking for
encapsulation, subtyping, inheritance, polymorphism, dynamic dispatch
and so on. Many of those are dead simple in Haskell. Others less so.
Unfortunately, it seems that most people trying to get these answers
are also trying to apply a design that is suboptimal for the language.
By the way, equality is a particularly nasty example given subtyping.
There is no good way to define equality that is fully polymorphic that
is also transitive and reflexive. Which is annoying no end.
On 1/28/07, apfelmus@quantentunnel.de
Donald Bruce Stewart wrote:
deliverable:
...In the tradition of the "letters of an ignorant newbie"...
What's the consensus on the OOP in Haskell *now*? There're some libraries such as OOHaskell, O'Haskell, and Haskell~98's own qualified type system with inheritance.
If I have GHC, which way to do anything OOP-like is considered "right" today?
Using existentials and typeclasses to do some OO things wouldn't be considered unidiomatic (particularly, using existentials to package up interfaces to values).
In general though, using a functional approach will produce better (simpler) Haskell code, and make it more likely others will understand it. Personally, I run in fear from OO Haskell ;)
Instead of OOP, Haskell uses (parametric) polymorphism which is more powerful than OOP. For instance, the function
length :: [a] -> Int
or, with an explicit forall
length :: forall a . [a] -> Int
counts the number of elements in a list "[a]", regardless of what type "a" those elements have. Moreover, it is guaranteed that "length" does not inspect or change the elements, because it must work for all types "a" the same way (this is called "parametricity"). Another example is
map :: (a -> b) -> [a] -> [b]
which maps a function over all elements in the list.
In addition, Haskell has type classes (which are similar to "interfaces" in OOP). The most basic example is
class Eq a where (==) :: a -> a -> Bool
Thus, you have an equality test available on all types that are instances of this class. For example, you can test whether two Strings are equal, because String is an instance of Eq. More generally, you say whether two lists are equal if you know how to test elements for equality:
instance Eq a => Eq [a] where [] == [] = True (x:xs) == (y:ys) = (x == y) && (xs == ys) _ == _ = False
The important thing I want to point out in this post is that parametric polymorphism is indeed more powerful than OOP: already a concept like Eq is impossible to implement in OOP. The problem is best illustrated with the class Ord (*), which provides an ordering relation. Let's concentrate on the "smaller than" function
(<) :: Ord a => a -> a -> Bool
Can I create an interface that expresses the same thing?
public interface Comparable { boolean smaller_than(?? y); }
No, because there is no type I can attribute to the second argument of "smaller_than". The problem is that I can only compare to values of the *same* type, i.e. the type which implements the interface.
Can I create a class the expresses the same thing?
public class Comparable { boolean smaller_than(Comparable y); }
This seems like a solution, but it is not. The problem is subtyping: if i make integers and strings members of this class, i would be able to compare the number 1 against the string "hello", which should be reported as a type error.
I have no formal proof, but I think that the "<" function cannot be expressed in a type correct way in OOP. AFAIK, only Java Generics can express the requirement we want:
interface Ord<A> { boolean smaller_than(A x, A y); }
class String implements Ord<String> { ... }
But Generics are a considerable extension to OOP. In fact, there is nothing really object oriented in here anymore, we're just on our way to parametric polymorphism.
My final remark is about what this means for the existential quantifier in Haskell. Because of the injection
inject :: forall a . a -> (exists a . a)
the existential quantifier can be thought of as implementing some form of subtyping, i.e. (exists a . a) is a supertype of every a. The point now is: given
type ExistsOrd = exists a . Ord a => a
there is *no*
instance Ord ExistsOrd where ...
because we could compare arbitrary subtypes of ExistsOrd then. In the end, the existental quantifier has limited use for data abstraction, it's "forall" that makes things happen.
Regards, apfelmus
(*) We don't consider Eq because given a test on type equality, we can generalize the signature of (==)
(==) :: (Eq a, Eq b) => a -> b -> Bool
Indeed, this is what OOP equality does.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

I'm going to be offensive, bigoted, and myopic for a minute here:
programming straight onto the Turing machine (and not too
dissimilarly, the von Neumann machine) is the act of making your
thoughts comprehensible to a little gizmo that exists to zip back and
forth on an infinite ticker tape. We should therefore abstract.
However, I am only marginally happier about making my thoughts
comprehensible to a tinkertoy set (which is how I regard object
oriented programming).
Why not just stay as close to mathematics as possible? Why the deep
desire to communicate your loftiest intentions to a tinkertoy set?
There was the Lambada project to map between Java's object hierarchies
and Haskell, however, and there was a lot of effort put into making
Haskell talk properly through COM. Both of those necessitate a model
of object oriented programming embedded in Haskell which would provide
you with prior art.
On 1/27/07, Alexy Khrabrov
...In the tradition of the "letters of an ignorant newbie"...
What's the consensus on the OOP in Haskell *now*? There're some libraries such as OOHaskell, O'Haskell, and Haskell~98's own qualified type system with inheritance.
If I have GHC, which way to do anything OOP-like is considered "right" today?
-- Frederick Ross Graduate Fellow, (|Siggia> + |McKinney>)/sqrt(2) Lab The Rockefeller University Je ne suis pas Fred Cross!

The primary goal of writing source code isn't to communicate to a
computer, but to communicate to a human being.
That implies that the communication should be at a high enough level
of abstraction to be easily understood by people, while not losing the
precision necessary for a computer.
OO, at least when done well, maps well to how people think. Things
that can be directed to perform actions. There is also a well
developed practice of OO analysis and design. It's not clear (at least
to me) that there is an equivalent set of practices for functional
programming.
It did take more than a decade for the industry to move from
structured analysis and design to OO, even when it was obvious to most
practioners that there was a horrible mismatch, and the models coming
out of analysis didn't apply.
The consensus answer to 'how do I implement my OO model in Haskell'
seems to be 'you're asking the wrong question'. But what is the right
question?
On 1/28/07, Frederick Ross
I'm going to be offensive, bigoted, and myopic for a minute here: programming straight onto the Turing machine (and not too dissimilarly, the von Neumann machine) is the act of making your thoughts comprehensible to a little gizmo that exists to zip back and forth on an infinite ticker tape. We should therefore abstract. However, I am only marginally happier about making my thoughts comprehensible to a tinkertoy set (which is how I regard object oriented programming).
Why not just stay as close to mathematics as possible? Why the deep desire to communicate your loftiest intentions to a tinkertoy set?
There was the Lambada project to map between Java's object hierarchies and Haskell, however, and there was a lot of effort put into making Haskell talk properly through COM. Both of those necessitate a model of object oriented programming embedded in Haskell which would provide you with prior art.
On 1/27/07, Alexy Khrabrov
wrote: ...In the tradition of the "letters of an ignorant newbie"...
What's the consensus on the OOP in Haskell *now*? There're some libraries such as OOHaskell, O'Haskell, and Haskell~98's own qualified type system with inheritance.
If I have GHC, which way to do anything OOP-like is considered "right" today?
-- Frederick Ross Graduate Fellow, (|Siggia> + |McKinney>)/sqrt(2) Lab The Rockefeller University Je ne suis pas Fred Cross! _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Steve Downey wrote: | OO, at least when done well, maps well to how people think. Things | that can be directed to perform actions. There is also a well | developed practice of OO analysis and design. It's not clear (at least | to me) that there is an equivalent set of practices for functional | programming. | [...] | The consensus answer to 'how do I implement my OO model in Haskell' | seems to be 'you're asking the wrong question'. But what is the right | question? That's a good question. In fact, it may even be the right question. (sorry, I'm having a bad week) The OO viewpoint of "objects with associated actions" is not entirely alien to Haskell/fp. Data types (abstract or concrete) are "classes of objects"; the "associated actions" are the functions that process and produce values of the given data type. The nature of functions allows an "action" to be associated with more than one object, relieving the programmer from a sometimes arbitrary choice:
data Car = ...
data Garage = ...
repair :: Garage -> Car -> Car
Should the "repair" action be associated with the garage or with the car? Well, with both, actually. (If this example does not convince you, you can probably think of better ones yourself.) Greetings, Arie

Steve Downey wrote:
OO, at least when done well, maps well to how people think.
Um, better duck. I am afraid you are about to draw some flames on that one. I hope people will try to be gentle. OO does NOT always map well to how most people think. OO maps well to how people trained in OO think. OO does provide abstraction, as you mentioned. It was the first such abstraction model that became popular. And abstraction was dearly needed at the time, so OO provided that need. But that doesn't mean OO is a good way of providing that abstraction. You'll find that Haskell provides the needed abstraction in a much cleaner, clearer, and consistent manner. I propose that the right question is: list exactly what kinds of abstraction OO provides, and why each is useful. Then, for each one, investigate how it is provided in Haskell. -Yitz

Yitzchak Gale wrote:
Steve Downey wrote:
OO, at least when done well, maps well to how people think.
Um, better duck. I am afraid you are about to draw some flames on that one. I hope people will try to be gentle.
No problem ;-) I'll never get tired quoting Dijkstra; one of the things that stuck in my mind is when he argues that 'the way people normally think' may simply not be appropriate to automatic computing aka programming, and that for this reason it may be contra-productive to appeal to this usual way of thinking -- however expedient it may seem in the short run. The failure of OO (to deliver on its many promises) IMHO nicely illustrates this. Of course people /like/ to think of 'objects' and their 'behavior' etc., it /is/ a very intuituive approach, because it is the way we are used to think. Unfortunately that doesn't necessarily make it effective for precise reasoning about the large and complex digital systems we are constructing. It may, in fact, be more effective to short-cut all these centuries (if not millenia) old thinking habits and cut straight to the chase: see programs as formulas to be reasoned about with formal methods (such as equational reasoning, which is a particularly good fit for Haskell with its equational notation and pure functional semantics). Cheers Ben

Hello Benjamin, Wednesday, January 31, 2007, 1:28:09 AM, you wrote:
course people /like/ to think of 'objects' and their 'behavior' etc., it /is/ a very intuituive approach, because it is the way we are used to think. Unfortunately that doesn't necessarily make it effective for precise reasoning about the large and complex digital systems we are constructing. It may, in fact, be more effective to short-cut all these centuries (if not millenia) old thinking habits and cut straight to the chase: see programs as formulas to be reasoned about with formal methods (such as equational reasoning, which is a particularly good fit for Haskell with its equational notation and pure functional semantics).
this drives us to the central problem - are computers created to makes people's lives easier or peoples created to make computers more productive? ;) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Steve Downey wrote:
The primary goal of writing source code isn't to communicate to a computer, but to communicate to a human being. That implies that the communication should be at a high enough level of abstraction to be easily understood by people, while not losing the precision necessary for a computer. OO, at least when done well, maps well to how people think. Things that can be directed to perform actions. There is also a well developed practice of OO analysis and design. It's not clear (at least to me) that there is an equivalent set of practices for functional programming.
Some of Haskell constructs come from the area of formal methods. Notably, algebraic types come from Z-notation (as I am told). Formal methods in general and Z notation in particular precede OO as defined, for example, in Smalltalk-80. Formal methods do not require substantial training and/or costly tools (although both exists). It can be trained in several weeks and start bringing benefits. Here are two surveys (somewhat outdated) on the use of formal methods in industry: http://citeseer.ifi.unizh.ch/39426.html http://citeseer.ifi.unizh.ch/craigen93international.html So, you can safely borrow methodics from formal methods and even think about Hindley-Milner type system as a theorem prover.

szefirov@ot.ru wrote:
Here are two surveys (somewhat outdated) on the use of formal methods in industry: http://citeseer.ifi.unizh.ch/39426.html http://citeseer.ifi.unizh.ch/craigen93international.html
Both of these links are dead. Could you post author and title? Thanks Ben

Benjamin Franksen wrote:
szefirov@ot.ru wrote:
Here are two surveys (somewhat outdated) on the use of formal methods in industry: http://citeseer.ifi.unizh.ch/39426.html http://citeseer.ifi.unizh.ch/craigen93international.html
Both of these links are dead. Could you post author and title?
Those are alive at the moment of email composing: http://citeseer.ist.psu.edu/39426.html *An International Survey of Industrial Applications of Formal Methods: Volume 1 Purpose, Approach, Analysis, and Conclusions (1993)* Dan Craigen, Susan Gerhart, Ted Ralston http://citeseer.ist.psu.edu/craigen93international.html *An International Survey of Industrial Applications of Formal Methods Volume 2 Case Studies (1993)* Dan Craigen, Susan Gerhart, Ted Ralston
participants (11)
-
Al Falloon
-
Alexy Khrabrov
-
apfelmus@quantentunnel.de
-
Arie Peterson
-
Benjamin Franksen
-
Bulat Ziganshin
-
dons@cse.unsw.edu.au
-
Frederick Ross
-
Steve Downey
-
szefirov@ot.ru
-
Yitzchak Gale