Perspectives on learning and using Haskell
I've spent part of the past few months learning Haskell and developing a moderately sized application. I came to this from a long background (20 years or so) of "conventional" programming in a variety of languages (from Fortran and Algol W to Java and Python). For me, learning Haskell has been one of the steepest learning curves of any new language that I have ever learned. Before this project, I was aware of some aspects of functional programming, but had never previously done any "in anger" (i.e. for real). Throughout this period, I've been accumulating some notes about some things that I found challenging along the way. The notes are not organized in any way, and they're certainly not complete. I've published them on my web site [1] in case the perspective might be useful to any "old hands" here. [1] http://www.ninebynine.org/Software/Learning-Haskell-Notes.html ... Also on the topic of perspectives: In recent conversation with a colleague, he mentioned to me that the term "functional programming" has an image problem. He suggested that the term conveys an impression of an approach that is staid, non-progressive or lacking novelty, and is prone to elicit a response of "been there, done that" from programmers who don't realize the full significance of the term "functional". I've also noticed that when I talk about "functional programming", some people tend to think I'm talking about using techniques like functions in C or Pascal (which is course is very desirable, but old hat and not worthy of great excitement). #g ------------ Graham Klyne For email: http://www.ninebynine.org/#Contact
On Tue, Dec 23, 2003 at 05:26:20PM +0000, Graham Klyne wrote:
Throughout this period, I've been accumulating some notes about some things that I found challenging along the way. The notes are not organized in any way, and they're certainly not complete. I've published them on my web site [1] in case the perspective might be useful to any "old hands" here.
[1] http://www.ninebynine.org/Software/Learning-Haskell-Notes.html
Thanks, that was a nice reading :) I have some comments: 8. Your explanation of Functor excludes many useful Functors which are rather not collections. For example, every monad (like IO) can be a Functor if you take fmap = Monad.liftM. For [] and Maybe this would give the same operation as in their normal instances. 11 and 18. If you define an instance of Monad for ((->) e) then return (putStrLn "Hello!") 'x' is a proper IO () value. Probably still not sensible ;) Special treatment of 'return' could be helpful, but I am afraid that it could also make it look special, like a return keyword in C. Best regards, Tom -- .signature: Too many levels of symbolic links
It occurs to me that Haskell would be quite a bit easier for OO and traditional programmers to grasp if Haskell would actually use the correct, or at least more commonly used, names for things. For instance, data Maybe a = Nothing | Just a Maybe is a type constructor and Nothing and Just are data constructors. So it makes me wonder why the use of the data keyword... wouldn't it make more sense to say: type Maybe a = Nothing | Just a ? Either that or perhaps change the descriptions "type constructor" and "data constructor" to something that fits with the keywords used. Likewise with class, type class, and instance: class Eq a where (==) :: a -> a -> Bool That actually declares a type class, not a class. So why the use of the keyword class? Is it done merely to confuse C++ and Java programmers? The concept of type class in Haskell apparently roughly corresponds to the concept of "interface" in Java. So why not call it interface? Instance is also confusing: instance Eq Integer where a == b = a `integerEq` b That actually declares that Integer is a type, not an "instance" in the traditional use of the word. A C++ programmer would probably use the word "subclass" instead of "instance". Then consider how different a meaning "return" has in Haskell than it does in C. ;) Does anyone else think this is a problem? If so, is it fixable? I guess from reading the many tutorials and FAQ's, that I'm in the same boat as everybody else. I consider myself a pretty bright boy, I've learned all kinds of other programming languages, from asm to forth to basic, pascal, C, C++, java, and C#... but this Haskell business, has me almost stumped. I mean, I understand the basic ideas pretty easily enough, but there seems to be such syntactical wierdness that to understand how to program in Haskell above the level of toy programs requires one to revisit every single design decision that went into making the language and its libraries, and grasp everything along the way, not only its function but also its peculiar nomenclature, and usually two different ways to say the same thing (maybe more). Only after following this long tortuous path will one ever be able to actually write useful programs. If Haskell (or any language of this style) is ever to gain a larger following, it would probably be wise to accomodate the existing programmer knowledge base a little more. I believe that the same core language, with cleaner design, different keywords, maybe different operators, would probably be readily accepted. There are many things that contribute to making Haskell less approachable, the above is just one. I wonder if there are any tutorials out there that provide a 1:1 mapping of concepts and idioms from other common languages into Haskell; small snippets of examples of pure translations would make things easier to grasp for some people than any amount of longwinded explanation. Probably there are easier ways to do the same things in Haskell, but it would be useful for beginners to get a unedited translation, even if that means heavy use of do-notation. At least people could then start writing imperative style Haskell programs immediately, and yeah that's not good style, but you can't learn good style if you can't accomplish anything and are stuck at square one. Frustratedly, Sean
to all: excuse my bad english. to javas: excuse my extreme opinions. - regard me as s.o. of an other... religion. to newbies: read it. to haskellers: you don't need to. johi, Sean. i remember that i've had the same problems with haskell, at the beginning. you are right, that there should be a special introduction just for imperative-programmers. but you are wrong, not haskell has to change sth. - the other languages have to do it, if anyone at all. but if the others are imperative languages, like all those you learned before, the change would imply to nullify their existence. ;)
asm to forth to basic, pascal, C, C++, java, and C#... i've learned the following: MS-DOS-3.3/5.0 .bat files QBASIC QUICKBASIC turbo-pascal + intel-asm delphi vc++ (while my university was/is_still teaching java like bill gates foists windows) aversed look at java - whatabullshit!!! (all the extremest down running prejudices -not knowing the language- seem to fit -especially after having learned the language-. the power of half-oop, easy to learn like risc-asm, with the speed of basic, and the no-compiletime-but-runtime-typechecking of cLisp or Tcl. but as a psychology student i'm fascinated about those obvious marketing-tricks, making s.o. believe in java.) cLisp haskell little bit prolog vc++ haskell vc++<stl> linux :) :) :) :) Tcl/Tk haskell c++<stl> math (!!!best!!! - but not a computer language) ...
so i know those cut and dried opinions one has by learning new languages. i've learned that there are at least two types of languages: the lower (->asm) and the higher (->math) ones. in c++ the difference between "struct" and "class" is that its default is "public" or "private". that has nearly nothing to do with classes - except oop. if you have data somewhere in memory, you call it an "instance" of a (struct- or class- or whatever-) type. in math you have types, sets, elements, classes, instances, ... (but not "interface" - don't think in java. a human-machine interface like monitor+keyboard+mouse is an interface, too. to define an interface does mean to use a pattern, not an special abstract-only--no-variable--no-default-functionimplementation--java-class to simulate cumbersomely multi-inheritance.) the language haskell is an attempt to implement math as computer language. (Haskell Brooks Curry was a genius who invented the banal function we call "curry".) any function has a type; the data in your memory has a type; combinations of functions and data_structures_in_memory have types. but a function is not a variable piece of memory - it depends on its definition, like a constant. the types of data structures, which are "instanciated" in memory, are defined with that data keyword in haskell. all types - functions too - are instances of classes; means: types are elements(instances) in special sets(classes), for which some individual attributes (in haskell: individual function-implementations) are defined. try to proof this view in haskell and c++. you will see, that the sense of oop-classes is not the definition of types but the unification of inherited types. some examples in c++ (didn't try to compile it): template<typename a> class Eq { protected: Eq(){} // This constructor exists just to be protected. public: virtual bool operator ==( const a& r ) const {return !( (*this) != r );} virtual bool operator !=( const a& r ) const {return !( (*this) == r );} }; template<typename a> struct Maybe : public virtual Eq<Maybe<a> > { enum Constructor_t {Nothing, Just}; union{ struct{ Constructor constructor_; }; struct{ Constructor constructorNothing; }; struct{ Constructor constructorJust; const a *data; }; }; Maybe() { constructorNothing = Nothing; } Maybe(const a& d) { constructorJust = Just; data = new a(d); } Maybe(const Maybe& m) { constructor_ = m.constructor_; if(m.constructorJust==Just) data = new a(*m.data); } ~Maybe() { if( constructorJust == Just ) delete data; } virtual bool operator ==( const Maybe& r ) const { switch( constructor_ ) { case Nothing: return (r.constructorNothing==Nothing); case Just: return (r.constructorJust !=Just) ? (false) : (*data==*r.data); } throw "undefined"; } }; // functionname :: (Eq a) => a -> returntype template<typename a> inline returntype functionname( const a& param ) { static_cast<const Eq<a>*>(¶m); // ignore result of casting, but test wether... param is instance / a (TYPE of param) is instance ...of Eq class. ... } merry xmas, - marc Am Mittwoch, 24. Dezember 2003 02:29 schrieb Sean L. Palmer:
It occurs to me that Haskell would be quite a bit easier for OO and traditional programmers to grasp if Haskell would actually use the correct, or at least more commonly used, names for things.
For instance,
data Maybe a = Nothing | Just a
Maybe is a type constructor and Nothing and Just are data constructors.
So it makes me wonder why the use of the data keyword... wouldn't it make more sense to say:
type Maybe a = Nothing | Just a
? Either that or perhaps change the descriptions "type constructor" and "data constructor" to something that fits with the keywords used.
Likewise with class, type class, and instance:
class Eq a where (==) :: a -> a -> Bool
That actually declares a type class, not a class. So why the use of the keyword class? Is it done merely to confuse C++ and Java programmers? The concept of type class in Haskell apparently roughly corresponds to the concept of "interface" in Java. So why not call it interface?
Instance is also confusing:
instance Eq Integer where a == b = a `integerEq` b
That actually declares that Integer is a type, not an "instance" in the traditional use of the word. A C++ programmer would probably use the word "subclass" instead of "instance".
Then consider how different a meaning "return" has in Haskell than it does in C. ;)
Does anyone else think this is a problem? If so, is it fixable?
I guess from reading the many tutorials and FAQ's, that I'm in the same boat as everybody else. I consider myself a pretty bright boy, I've learned all kinds of other programming languages, from asm to forth to basic, pascal, C, C++, java, and C#... but this Haskell business, has me almost stumped. I mean, I understand the basic ideas pretty easily enough, but there seems to be such syntactical wierdness that to understand how to program in Haskell above the level of toy programs requires one to revisit every single design decision that went into making the language and its libraries, and grasp everything along the way, not only its function but also its peculiar nomenclature, and usually two different ways to say the same thing (maybe more). Only after following this long tortuous path will one ever be able to actually write useful programs.
If Haskell (or any language of this style) is ever to gain a larger following, it would probably be wise to accomodate the existing programmer knowledge base a little more. I believe that the same core language, with cleaner design, different keywords, maybe different operators, would probably be readily accepted.
There are many things that contribute to making Haskell less approachable, the above is just one.
I wonder if there are any tutorials out there that provide a 1:1 mapping of concepts and idioms from other common languages into Haskell; small snippets of examples of pure translations would make things easier to grasp for some people than any amount of longwinded explanation. Probably there are easier ways to do the same things in Haskell, but it would be useful for beginners to get a unedited translation, even if that means heavy use of do-notation. At least people could then start writing imperative style Haskell programs immediately, and yeah that's not good style, but you can't learn good style if you can't accomplish anything and are stuck at square one.
Frustratedly, Sean
On Dec 24, 2003, at 2:29 AM, Sean L. Palmer wrote:
It occurs to me that Haskell would be quite a bit easier for OO and traditional programmers to grasp if Haskell would actually use the correct, or at least more commonly used, names for things.
I don't think changing a few keywords will have any significant impact; the differences between Haskell and Java run much, much deeper.
So it makes me wonder why the use of the data keyword... wouldn't it make more sense to say: type Maybe a = Nothing | Just a
No, it wouldn't. There is a difference between a `type' and a `datatype': a datatype is a special kind of type which comes equipped with a set of functions---the data constructors---which interact nicely with pattern-matching so that one can determine exhaustiveness and non-ambiguity of matches. Types in general, for example the Double type, do not satisfy these conditions.
Likewise with class, type class, and instance: class Eq a where (==) :: a -> a -> Bool That actually declares a type class, not a class.
According to the normal rules of English, every `type class' is necessarily a `class', isn't it?
So why the use of the keyword class? Is it done merely to confuse C++ and Java programmers?
Yikes! The secret is out! ;)
The concept of type class in Haskell apparently roughly corresponds to the concept of "interface" in Java. So why not call it interface?
Haskell type classes are older than Java. Perhaps you should petition Sun instead?
Instance is also confusing: instance Eq Integer where a == b = a `integerEq` b That actually declares that Integer is a type, not an "instance" in the traditional use of the word.
No, that Integer is a type is a necessary precondition of this instance declaration. The declaration rather says that Integer belongs to the type class Eq. The choice of the syntax `instance' here probably arises from the idea that a type class is relation (predicate) on types; many people say that, for example, (x,y) `is an instance of' the relation R if x R y.
A C++ programmer would probably use the word "subclass" instead of "instance".
Not really. Up above you already compared type classes to Java interfaces. It follows that a Haskell instance T of class C rather corresponds to a Java class T which implements an interface C.
Then consider how different a meaning "return" has in Haskell than it does in C. ;)
"return" was probably chosen precisely because of what it suggests by analogy with C's return. Of course there are big differences, but can you think of a better name?
Does anyone else think this is a problem?
I think any difficulties stemming from Haskell's choice of keywords are dwarfed by the differences stemming from Haskell's semantics.
If so, is it fixable?
Haskell is much too old to be changing its surface syntax. Of course, you can always change GHC's input grammar, fork it, call it Haskell++ and see if anybody will use it. :) Or use Template Haskell.
I guess from reading the many tutorials and FAQ's, that I'm in the same boat as everybody else. I consider myself a pretty bright boy, I've learned all kinds of other programming languages, from asm to forth to basic, pascal, C, C++, java, and C#... but this Haskell business, has me almost stumped.
The standard response is: "It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration." -- Edsger Dijkstra, How do we tell truths that might hurt? http://www.cs.virginia.edu/~evans/cs655/readings/ewd498.html
I mean, I understand the basic ideas pretty easily enough, but there seems to be such syntactical wierdness that to understand how to program in Haskell above the level of toy programs requires one to revisit every single design decision that went into making the language and its libraries, and grasp everything along the way, not only its function but also its peculiar nomenclature, and usually two different ways to say the same thing (maybe more). Only after following this long tortuous path will one ever be able to actually write useful programs.
IMO, there really isn't much `syntactical weirdness' in Haskell; it has a pretty accessible syntax and first-time programming students appear to exhibit largely the same problems with Haskell syntax as they would in other languages (forgotten parentheses, etc.). What you are really complaining about is Haskell's semantics, but you don't realize it yet.
If Haskell (or any language of this style) is ever to gain a larger following, it would probably be wise to accomodate the existing programmer knowledge base a little more. I believe that the same core language, with cleaner design, different keywords, maybe different operators, would probably be readily accepted.
I believe you are very mistaken on that count. Is Howard Dean sure to win the American election if he starts speaking with a Texas accent? Anyway, most of us believe Haskell already has a cleaner design than other languages.
I wonder if there are any tutorials out there that provide a 1:1 mapping of concepts and idioms from other common languages into Haskell; small snippets of examples of pure translations would make things easier to grasp for some people than any amount of longwinded explanation.
I don't know of any, but you can look here: http://www.haskell.org/bookshelf/
Probably there are easier ways to do the same things in Haskell, but it would be useful for beginners to get a unedited translation, even if that means heavy use of do-notation. At least people could then start writing imperative style Haskell programs immediately, and yeah that's not good style, but you can't learn good style if you can't accomplish anything and are stuck at square one.
What is it you want to accomplish? If you post specific questions, maybe people can help you. I think the approach you outline is not really a good one. Though I think it is helpful to point out analogies between language concepts, Haskell will indeed be frustrating to use if you write your programs by translation, so to speak, and people tend to develop both good and bad habits early. The Haskell paradigm is indeed quite different from the C/C++/Java paradigm, so you might have to relearn quite a bit before you can start integrating concepts and techniques you've already acquired. But if Haskell were just another clone of C, what would be the point of learning it? You might as well use Java. The point of learning Haskell should not be merely to learn how to re-express what you already know in a different syntax; it should be to learn genuinely new things, and to get a fundamentally different perspective on computing---the pure functional paradigm. Regards, Frank
Sean L. Palmer wrote:
class Eq a where (==) :: a -> a -> Bool
That actually declares a /type class/, not a class. So why the use of the keyword class? Is it done merely to confuse C++ and Java programmers? The concept of type class in Haskell apparently roughly corresponds to the concept of "interface" in Java. So why not call it interface?
According to dictionary.com one of the definitions of the word class is: A set, collection, group, or configuration containing members regarded as having certain attributes or traits in common; a kind or category. And what the members of class Eq have in common is that they have a function (==). So to me it seems that the word "class" is very well chosen; it describes what's going on. Now, I admit that if you think you can take concepts with similar names from other programming languages and apply them to Haskell you might get confused. You might come across what is called "false friends" in natural language, i.e., words that look the same but mean different things. -- Lennart
G'day all. Quoting Lennart Augustsson <lennart@augustsson.net>:
According to dictionary.com one of the definitions of the word class is:
A set, collection, group, or configuration containing members regarded as having certain attributes or traits in common; a kind or category.
And what the members of class Eq have in common is that they have a function (==). So to me it seems that the word "class" is very well chosen; it describes what's going on.
Right. It's exactly the same way that Java and C++ use the word "class". A class is a set of types. In the case of Eq, it's the set of types which support the equality testing operation (==). The problem is that C++ (and Java, but I'll use C++ as the archetype from now on) uses the one keyword, "class" to do multiple tasks. When you declare a C++ class: class Foo { // something }; you're actually doing three things. You are defining a class of types, namely, the set of types which are derived (possibly in zero steps) from Foo. You are also defining a concrete type, namely Foo. Finally, you are declaring that the concrete type Foo is a member of the class Foo. Haskell decouples these three tasks. To define a class, you use "class". To define a concrete type you use "data". To declare that a certain concrete type is a member of a class, you use "instance". I should point out that C++ has an idiom something like Haskell type classes, which is the "concept". Concepts are, I think, an admission that OO derivation is often not the most appropriate way to implement an abstract interface. Concepts are not statically checked by default, but there are good libraries out there which effectively provide static checking of concepts. A good C++ programmer would probably not implement Eq as a C++ class because (as Haskell programmers already know), Eq doesn't make sense as a Liskov-substitutable concrete type on its own. Rather, a good C++ programmer would provide the interface for the STL "equality comparable concept", which is pretty much the same as Eq.
Now, I admit that if you think you can take concepts with similar names from other programming languages and apply them to Haskell you might get confused. You might come across what is called "false friends" in natural language, i.e., words that look the same but mean different things.
Well, in this case, what Haskell calls a "class" is a strict subset of what C++ calls a "class", so it's more of a true friend than a false one. It's C++'s fault (though it is historically understandable) that the "class" keyword does more than just declare a class of types. Cheers, Andrew Bromage
That was quite a satisfying explanation, thank you. That is certainly clearing a few things up. Sean ----- Original Message ----- From: <ajb@spamcop.net> To: <haskell@haskell.org> Sent: Friday, December 26, 2003 3:07 AM Subject: Re: Haskell naming conventions
G'day all.
Quoting Lennart Augustsson <lennart@augustsson.net>:
According to dictionary.com one of the definitions of the word class is:
A set, collection, group, or configuration containing members regarded as having certain attributes or traits in common; a kind or category.
And what the members of class Eq have in common is that they have a function (==). So to me it seems that the word "class" is very well chosen; it describes what's going on.
Right. It's exactly the same way that Java and C++ use the word "class". A class is a set of types. In the case of Eq, it's the set of types which support the equality testing operation (==).
The problem is that C++ (and Java, but I'll use C++ as the archetype from now on) uses the one keyword, "class" to do multiple tasks. When you declare a C++ class:
class Foo { // something };
you're actually doing three things. You are defining a class of types, namely, the set of types which are derived (possibly in zero steps) from Foo. You are also defining a concrete type, namely Foo. Finally, you are declaring that the concrete type Foo is a member of the class Foo.
Haskell decouples these three tasks. To define a class, you use "class". To define a concrete type you use "data". To declare that a certain concrete type is a member of a class, you use "instance".
I should point out that C++ has an idiom something like Haskell type classes, which is the "concept". Concepts are, I think, an admission that OO derivation is often not the most appropriate way to implement an abstract interface. Concepts are not statically checked by default, but there are good libraries out there which effectively provide static checking of concepts.
A good C++ programmer would probably not implement Eq as a C++ class because (as Haskell programmers already know), Eq doesn't make sense as a Liskov-substitutable concrete type on its own. Rather, a good C++ programmer would provide the interface for the STL "equality comparable concept", which is pretty much the same as Eq.
Now, I admit that if you think you can take concepts with similar names from other programming languages and apply them to Haskell you might get confused. You might come across what is called "false friends" in natural language, i.e., words that look the same but mean different things.
Well, in this case, what Haskell calls a "class" is a strict subset of what C++ calls a "class", so it's more of a true friend than a false one. It's C++'s fault (though it is historically understandable) that the "class" keyword does more than just declare a class of types.
Cheers, Andrew Bromage _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
On 23-Dec-2003, Sean L. Palmer <seanpalmer@verizon.net> wrote:
It occurs to me that Haskell would be quite a bit easier for OO and traditional programmers to grasp if Haskell would actually use the correct, or at least more commonly used, names for things.
For instance,
data Maybe a = Nothing | Just a
Maybe is a type constructor and Nothing and Just are data constructors.
So it makes me wonder why the use of the data keyword... wouldn't it make more sense to say:
type Maybe a = Nothing | Just a
?
I agree. That's one of the reasons why Mercury uses the word "type" rather than "data" when declaring discriminated union types. The corresponding declaration in Mercury is :- type maybe(A) ---> nothing ; just(A).
Likewise with class, type class, and instance:
class Eq a where (==) :: a -> a -> Bool
That actually declares a type class, not a class. So why the use of the keyword class? Is it done merely to confuse C++ and Java programmers?
This is indeed potentially confusing for programmers familiar with C++/Java/C#/Ada/etc. In Mercury, we adopted Haskell-style type classes, using semantics very similar to those in Haskell. But we did adapt the syntax a bit. In particular, we use "typeclass" rather than "class" for type class declarations. So in Mercury, the corresponding declaration would look like this: :- typeclass eq(A) where [ func '=='(A, A) = bool ].
The concept of type class in Haskell apparently roughly corresponds to the concept of "interface" in Java. So why not call it interface?
Haskell interfaces are really quite a bit more general than Java interfaces, particularly when you consider common extensions such as multi-parameter type classes, constructor classes, and functional dependencies. So I think it would not help to use the word "interface". -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
In recent conversation with a colleague, he mentioned to me that the term "functional programming" has an image problem. He suggested that the term
short komment: "meta programming" and "meta-language" makes people curious, "functional programming" seems to have the opposite effect. merry xmas - marc Am Dienstag, 23. Dezember 2003 18:26 schrieb Graham Klyne:
I've spent part of the past few months learning Haskell and developing a moderately sized application. I came to this from a long background (20 years or so) of "conventional" programming in a variety of languages (from Fortran and Algol W to Java and Python). For me, learning Haskell has been one of the steepest learning curves of any new language that I have ever learned. Before this project, I was aware of some aspects of functional programming, but had never previously done any "in anger" (i.e. for real).
Throughout this period, I've been accumulating some notes about some things that I found challenging along the way. The notes are not organized in any way, and they're certainly not complete. I've published them on my web site [1] in case the perspective might be useful to any "old hands" here.
[1] http://www.ninebynine.org/Software/Learning-Haskell-Notes.html
...
Also on the topic of perspectives:
In recent conversation with a colleague, he mentioned to me that the term "functional programming" has an image problem. He suggested that the term conveys an impression of an approach that is staid, non-progressive or lacking novelty, and is prone to elicit a response of "been there, done that" from programmers who don't realize the full significance of the term "functional". I've also noticed that when I talk about "functional programming", some people tend to think I'm talking about using techniques like functions in C or Pascal (which is course is very desirable, but old hat and not worthy of great excitement).
#g
------------ Graham Klyne For email: http://www.ninebynine.org/#Contact
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
participants (8)
-
ajb@spamcop.net -
Fergus Henderson -
Frank Atanassow -
Graham Klyne -
Lennart Augustsson -
Marc A. Ziegert -
Sean L. Palmer -
Tomasz Zielonka