Re: [Haskell-cafe] Design Patterns by Gamma or equivalent

Mark Spezzano wrote:
Because Haskell is not OO, it is functional, I was wondering if there is some kind of analogous “design pattern”/”template” type concept that describe commonly used functions that can be “factored out” in a general sense to provide the same kind of usefulness that Design Patterns do for OOP. Basically I’m asking if there are any kinds of “common denominator” function compositions that are used again and again to solve problems. If so, what are they called?
Most of the (particular) problems OO design patterns solve are non-issues in Haskell because the language is more expressive. The issues giving rise to patterns like Visitor and Factory are non-issues, so their "solutions" are trivial. A number of other patterns can actually be written down once and for all (in higher-order functions like foldr, map,...) instead of needing repetition. But that's not to say we don't have our own expressiveness deficiencies ;) The analogous term for the genre is "functional pearl", though the individual pearls don't tend to be as codified as in OOP. One example is using coproducts for open unions[1] which solves the dual problem to Visitor. Another is using open recursion[2]. A third example along the same track is using two-level types[3]. But again a lot of the patterns, once discovered, get turned into libraries that can be used off the shelf: e.g. the two-continuation solution for efficient and fair backtracking search[4], and list-fusion techniques[5]. There also a number of "idioms" which are similar in scope to the idioms that arise in other languages: using tail recursion, accumulators, continuation-passing transformations, closures over recursion[6], Schwartzian transforms, etc. And then there are some things like monoids which fall somewhere between idiom and pearl. Some specific OO patterns have direct analogues in "defunctionalization"[7]. For the most part defunctionalization is something best left to the compiler, but on occasion we want to be explicit about it and this too is an idiom/pearl border case IMO. And, of course, there's the entire cottage industry of using category theory for fun and profit. [1] http://www.cs.nott.ac.uk/~wss/Publications/DataTypesALaCarte.pdf [2] http://www.cs.utexas.edu/~wcook/Drafts/2006/MemoMixins.pdf [3a] http://web.cecs.pdx.edu/~sheard/papers/generic.ps [3b] http://web.cecs.pdx.edu/~sheard/papers/JfpPearl.ps [4a] http://okmij.org/ftp/papers/LogicT.pdf [4b] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/logict [5a] http://www.cse.unsw.edu.au/~dons/papers/CSL06.html [5b] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/bytestring [5c] http://www.cse.unsw.edu.au/~dons/papers/CLS07.html [5d] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/stream-fusion [5e] http://homepages.inf.ed.ac.uk/wadler/papers/vanish/vanish.pdf [6] For lack of a better name. I mean doing this:
-- Here the a,b,c,d variables are captured in the closure for go recursive a b c d = go where go 0 = ...a...b... go n = ...c...d...go (n-1)
instead of this:
-- ...instead of needing to be passed through the recursion each time recursive a b c d 0 = ...a...b... recursive a b c d n = ...c...d...recursive a b c d (n-1)
[7a] http://blog.plover.com/prog/defunctionalization.html -- Live well, ~wren

wren:
There also a number of "idioms" which are similar in scope to the idioms that arise in other languages: using tail recursion, accumulators, continuation-passing transformations, closures over recursion[6], Schwartzian transforms, etc.
[6] For lack of a better name. I mean doing this:
-- Here the a,b,c,d variables are captured in the closure for go recursive a b c d = go where go 0 = ...a...b... go n = ...c...d...go (n-1)
instead of this:
-- ...instead of needing to be passed through the recursion each time recursive a b c d 0 = ...a...b... recursive a b c d n = ...c...d...recursive a b c d (n-1)
Static argument transformation: http://hackage.haskell.org/trac/ghc/ticket/888 http://www.haskell.org/pipermail/cvs-ghc/2008-April/041959.html Or more generally worker/wrapper http://www.workerwrapper.com/ Take your pick :)

G'day all.
Quoting wren ng thornton
Most of the (particular) problems OO design patterns solve are non-issues in Haskell because the language is more expressive.
...and vice versa. Some of the "design patterns" that we use in Haskell, for example, are to overcome the fact that Haskell doesn't have mutable global state.
A number of other patterns can actually be written down once and for all (in higher-order functions like foldr, map,...) instead of needing repetition.
This is also true in many OO languages. A lot of the GoF book, for example, can be implemented as libraries in Ada or C++.
And then there are some things like monoids which fall somewhere between idiom and pearl.
"Things like monoids" are constructions from algebra. Abstract algebra and design patterns have a lot in common. They're based on the same idea, in fact: When a pattern keeps showing up, define it and give it a name so you can talk about it independently of any specific implementation. Or to put it another way, category theory is the pattern language of mathematics. Cheers, Andrew Bromage

ajb@spamcop.net wrote:
G'day all.
Quoting wren ng thornton
: Most of the (particular) problems OO design patterns solve are non-issues in Haskell because the language is more expressive.
...and vice versa. Some of the "design patterns" that we use in Haskell, for example, are to overcome the fact that Haskell doesn't have mutable global state.
Oh sure. However, in my experience the most common design patterns of OO are the ones obviated in functional languages. And I haven't tended to need any of the global mutation patterns in Haskell[1]. Not an objective analysis by any means, but I do think it holds more water than it leaks. The whole genre of SYB papers indicates that there's no panacea. [1] The two times I've needed global mutation, one is for arbitrary unique symbol generation (uses a library), and the other is for doing some very tricky memoization with self-compaction when memory is low. The latter I'd think is certainly too special-purpose to be considered a "pattern".
A number of other patterns can actually be written down once and for all (in higher-order functions like foldr, map,...) instead of needing repetition.
This is also true in many OO languages. A lot of the GoF book, for example, can be implemented as libraries in Ada or C++.
I think this depends very much on the specific language in question. For dynamic OO languages with lambdas (Smalltalk, Ruby, Python, Perl) it's easy, but then it's basically the same thing. For languages with a way of doing mixins (the aforementioned, C++) it's also pretty easy. But for languages like Java, oftentimes it's a choice between impossible and grossly inefficient. I've been dealing with a lot of Java lately. Certainly it's _possible_ to do in any language (Turing tarpit et al.), but the question is one of how much boilerplate is involved and how efficient it is. I think the latter point is important not only for the projects I've worked on, but also for how widely adopted any given pattern becomes; many people are fastidious about performance. The former is also important to whether it gets spread as a "pattern" or whether it gets packaged up in a library somewhere.
And then there are some things like monoids which fall somewhere between idiom and pearl.
"Things like monoids" are constructions from algebra.
Abstract algebra and design patterns have a lot in common. They're based on the same idea, in fact: When a pattern keeps showing up, define it and give it a name so you can talk about it independently of any specific implementation.
Or to put it another way, category theory is the pattern language of mathematics.
Indeed. Though, IMO, there's a distinction between fairly banal things (e.g. monoids), and the other more interesting bits of category theory and abstract algebra. Monoids often occur by happenstance and so their triviality lends to being more like an idiom. Similarly, functors also tend to just happen. However, once you start getting into applicative functors, natural transformations, and the like, you've made a step from incidentally using a ubiquitous pattern of mathematics, to making a concerted effort at abstraction. -- Live well, ~wren

Am Dienstag, 17. März 2009 05:09 schrieb wren ng thornton:
ajb@spamcop.net wrote:
Or to put it another way, category theory is the pattern language of mathematics.
Indeed. Though, IMO, there's a distinction between fairly banal things (e.g. monoids),
Monoids aren’t a concept of category theory. There are a generalization of groups. So they more belong to group theory. By the way, the documentation of Control.Category says that a category is a monoid (as far as I remember). This is wrong. Category laws correspond to monoid laws but monoid composition is total while category composition has the restriction that the domain of the first argument must match the codomain of the second. Best wishes, Wolfgang

"Wolfgang" == Wolfgang Jeltsch
writes:
Wolfgang> By the way, the documentation of Control.Category says Wolfgang> that a category is a monoid (as far as I remember). This Wolfgang> is wrong. Category laws correspond to monoid laws but Wolfgang> monoid composition is total while category composition Wolfgang> has the restriction that the domain of the first Wolfgang> argument must match the codomain of the second. I'm reading the Barr/Wells slides at the moment, and they say the following: "Thus a category can be regarded as a generalized monoid, or a 'monoid with many objects'" -- Colin Adams Preston Lancashire

Am Dienstag, 17. März 2009 10:54 schrieben Sie:
Wolfgang Jeltsch
writes: By the way, the documentation of Control.Category says that a category is a monoid (as far as I remember). This is wrong. Category laws correspond to monoid laws but monoid composition is total while category composition has the restriction that the domain of the first argument must match the codomain of the second.
I'm reading the Barr/Wells slides at the moment, and they say the following:
"Thus a category can be regarded as a generalized monoid,
What is a “generalized monoid”? According to the grammatical construction (adjective plus noun), it should be a special kind of monoid, like a commutative monoid is a special kind of monoid. But then, monoids would be the more general concept and categories the special case, quite the opposite of how it really is. A category is not a “generalized monoid” but categories (as a concept) are a generalization of monoids. Each category is a monoid, but not the other way round. A monoid is clearly defined as a pair of a set M and a (total) binary operation over M that is associative and has a neutral element. So, for example, the category of sets and functions is not a monoid. First, function composition is not total if you allow arbitrary functions as its arguments. Second, the collection of all sets is not itself a set (but a true class) which conflicts with the above definition which says that M has to be a set.
or a 'monoid with many objects'"
What is a monoid with many objects? Best wishes, Wolfgang

On Tue, 2009-03-17 at 13:06 +0100, Wolfgang Jeltsch wrote:
Am Dienstag, 17. März 2009 10:54 schrieben Sie:
Wolfgang Jeltsch
writes: By the way, the documentation of Control.Category says that a category is a monoid (as far as I remember). This is wrong. Category laws correspond to monoid laws but monoid composition is total while category composition has the restriction that the domain of the first argument must match the codomain of the second.
I'm reading the Barr/Wells slides at the moment, and they say the following:
"Thus a category can be regarded as a generalized monoid,
What is a “generalized monoid”? According to the grammatical construction (adjective plus noun), it should be a special kind of monoid, like a commutative monoid is a special kind of monoid. But then, monoids would be the more general concept and categories the special case, quite the opposite of how it really is.
A category is not a “generalized monoid” but categories (as a concept) are a generalization of monoids. Each category is a monoid, but not the other way round.
You mean ``each monoid is a category, but not the other way round''.
A monoid is clearly defined as a pair of a set M and a (total) binary operation over M that is associative and has a neutral element. So, for example, the category of sets and functions is not a monoid. First, function composition is not total if you allow arbitrary functions as its arguments. Second, the collection of all sets is not itself a set (but a true class) which conflicts with the above definition which says that M has to be a set.
or a 'monoid with many objects'"
What is a monoid with many objects?
A categorical definition of a monoid (that is, a plain old boring monoid in Set) is that it is a category with a single object. A category is thus a monoid with the restriction to a single object lifted :) jcc

Am Dienstag, 17. März 2009 16:32 schrieben Sie:
On Tue, 2009-03-17 at 13:06 +0100, Wolfgang Jeltsch wrote:
A category is not a “generalized monoid” but categories (as a concept) are a generalization of monoids. Each category is a monoid, but not the other way round.
You mean ``each monoid is a category, but not the other way round''.
Exactly. :-)
What is a monoid with many objects?
A categorical definition of a monoid (that is, a plain old boring monoid in Set) is that it is a category with a single object. A category is thus a monoid with the restriction to a single object lifted :)
Okay. Well, a monoid with many objects isn’t a monoid anymore since a monoid has only one object. It’s the same as with: “A ring is a field whose multiplication has no inverse.” One usually knows what is meant with this but it’s actually wrong. Wrong for two reasons: First, because the multiplication of a field has an inverse. Second, because the multiplication of a ring is not forced to have no inverse but may have one. It reminds me of a definition of “constant” in programming languages which occured in some literature: “A constant is a variable whose value cannot be changed.” :-) Best wishes, Wolfgang

On Tue, Mar 17, 2009 at 5:06 AM, Wolfgang Jeltsch
What is a “generalized monoid”? According to the grammatical construction (adjective plus noun), it should be a special kind of monoid
There's no such implication in English. The standard example used by linguists is "fake gun". -- Dan

Am Dienstag, 17. März 2009 18:43 schrieben Sie:
On Tue, Mar 17, 2009 at 5:06 AM, Wolfgang Jeltsch
wrote: What is a “generalized monoid”? According to the grammatical construction (adjective plus noun), it should be a special kind of monoid
There's no such implication in English. The standard example used by linguists is "fake gun".
Okay, but this is a corner case isn’t it? And the phrase “generalized monoid” has another problem. It’s not a single monoid that is generalized but the “monoid concept”. The class of monoids is extended to become the class of categories. Best wishes, Wolfgang

Wolfgang Jeltsch
Am Dienstag, 17. März 2009 18:43 schrieben Sie:
There's no such implication in English. The standard example used by linguists is "fake gun". Okay, but this is a corner case isn???t it?
Perhaps (depending on what you consider to be a corner case). But then why not take "generalized monoid" to be a corner case too?
And the phrase ???generalized monoid??? has another problem. It???s not a single monoid that is generalized but the ???monoid concept???. The class of monoids is extended to become the class of categories.
I'm not sure what problem you mean. Perhaps you have in mind a grammar that defines what strings are well-formed English sentences and a semantics that specifies their denotations (say, their truth conditions), such that it turns out that the meaning of "generalized monoid" is inappropriate. But what do you have in mind? Linguists typically take adjectives to denote functions from noun meanings to noun meanings. Because linguists also typically take nouns to denote functions, adjectives end up denoting higher-order functions. That's why this message is still generalized on-topic. :) -- Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig Who would have thought LISP would come back to life. Steve Bourne, in an interview about Bourne Shell.

Wolfgang Jeltsch wrote:
Am Dienstag, 17. März 2009 10:54 schrieben Sie:
I'm reading the Barr/Wells slides at the moment, and they say the following:
"Thus a category can be regarded as a generalized monoid,
What is a “generalized monoid”? According to the grammatical construction (adjective plus noun), it should be a special kind of monoid, like a commutative monoid is a special kind of monoid. But then, monoids would be the more general concept and categories the special case, quite the opposite of how it really is.
Usually in math texts "a Y is a generalized X" means exactly "Ys are a generalization of Xs", and thus Y is the larger class of objects got by relaxing some law in X. It's a description, not a name. E.g. Hilbert space is a generalized Euclidean space, Heyting algebras are generalized Boolean algebras, modules are generalized vector spaces, etc. The compounding adjective+name=name scheme used for "commutative X" and such doesn't apply when the adjective happens to be "generalized". That scheme isn't a general rule of English anyways (only a common rule of mathematics), as with Dan Piponi's "fake gun". -- Live well, ~wren

Am Mittwoch, 18. März 2009 05:36 schrieb wren ng thornton:
Wolfgang Jeltsch wrote:
Am Dienstag, 17. März 2009 10:54 schrieben Sie:
I'm reading the Barr/Wells slides at the moment, and they say the following:
"Thus a category can be regarded as a generalized monoid,
What is a “generalized monoid”? According to the grammatical construction (adjective plus noun), it should be a special kind of monoid, like a commutative monoid is a special kind of monoid. But then, monoids would be the more general concept and categories the special case, quite the opposite of how it really is.
Usually in math texts "a Y is a generalized X" means exactly "Ys are a generalization of Xs", and thus Y is the larger class of objects got by relaxing some law in X. It's a description, not a name. E.g. Hilbert space is a generalized Euclidean space, Heyting algebras are generalized Boolean algebras, modules are generalized vector spaces, etc.
I know these phrases but I always considered them as something, mathematicians use when they talk to each other informally, not what they would write in a book. Best wishes, Wolfgang
participants (8)
-
ajb@spamcop.net
-
Chung-chieh Shan
-
Colin Paul Adams
-
Dan Piponi
-
Don Stewart
-
Jonathan Cast
-
Wolfgang Jeltsch
-
wren ng thornton