Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Haskell
Wiki community
Recent changes
Random page
HaskellWiki
Search
Search
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Diagrams/Dev/Expression
(section)
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Special pages
Page information
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
= The problem = The [http://en.wikipedia.org/wiki/Expression_problem Expression Problem], coined by Phil Wadler, describes a situation where you have a sum type and some operations on it; the problem is to be able to both add new cases to the sum type as well as add new operations. Some approaches, e.g. OOP, make it easy to add new disjuncts (just make a new subclass, and implement all the appropriate methods) but annoying to add new operations (you have to go back through and add a new method implementation for every existing class); others, e.g. algebraic data types, make it easy to add new operations (just write a new function) but annoying to add new disjuncts (you can add a new constructor to your data type but then you have to go through and add a new case to the implementation of every existing function). This problem shows up, in a disguised form, in diagrams. Our "sum type" is the set of primitives that can be used to build diagrams; our "operations" are different backends. We have adopted a somewhat more dynamic solution: primitives can be any type, and backends declare which primitives they can handle by implementing an instance of <code>Renderable</code>. This means that new primitives can be easily added (just make a new type; it does not require changing existing backends, which will simply not be able to render it) but also new backends. This is sort of like having an algebraic data type for primitives, but allowing the backends (thought of as functions) to have "incomplete pattern matching", i.e. to simply not handle some primitives. Literally implementing it that way would be undesirable, however, because then handing a diagram to a backend which contained primitives it did not handle would cause the program to crash with a runtime pattern match failure. Note, if we did away with the ability of different backends to support different primitive types, these problems would all go away. We could just have a single algebraic data type specifying the static list of primitives that all backends must support, and that would be that. (This is the approach taken by many simpler drawing libraries, e.g. gloss.) However, (it seems to me at least) that the added flexibility of backends which can't support certain primitives, or support extra special backend-specific primitives, is a really nice feature that would be very painful to give up.
Summary:
Please note that all contributions to HaskellWiki are considered to be released under simple permissive license (see
HaskellWiki:Copyrights
for details). If you don't want your writing to be edited mercilessly and redistributed at will, then don't submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!
Cancel
Editing help
(opens in new window)
Toggle limited content width