From the most general systemic perspective, a functional modeling relates to the modeling of objects or relations which have an objective/goal. It is a construction of algorithms realizing a process leading or necessary for the achieving this goal. Functional modeling can relate to an existing or mental/planned entities. In the case of the existing real world systems or processes, a functional modeling produces the model which exhibits only goal-oriented properties of the modeled entity. It means, a functional representation of the modeled entity does not need to represent its real construction (see, Adam M. Gadomski, 1988, http://erg4146.casaccia.enea.it/wwwerg26701/gad-diag0.htm - visited 9 Oct. 2010) In the case of software programming, the functional specification of an application is frequently independent yet on the language of its concrete implementation.
In investigating FunctionalProgrammingLanguages for a project, the main thing that hit me was that there's no clear way to model real things in the problem space. It has to be done through some combination of complicated data structures and modules.
This is funny because about the only thing FP is used for in industry is to model extremely complex things like semiconductors, telecom networks and financial markets.
Let's say I have a car. It has an engine with multiple pistons, it is multiple tires, etc. How would I model this and perform operations in a functional language? How would I able to perform some generic car operations and special operations specific to that model of car?
Would it be something like have Ford250 module. At this point there's no inheritance so I couldn't in a type safe way have a car base class and perform operations on it. In the Ford250 module, I would have a data structure with all the parts. It would be a complicated data structure. There are obviously multiple instances of these trucks, so I would have to have a name for it. Then if I wanted the pressure recommendation for the left front tire, I would go:
get_pressure_recommendation(truck name, tire position)Any help here?
OO modelling is fundamentally broken. You always go "there is this, there is that, it has this, it contains that". Now it sits there, but what does it do? Nothing at all, according to your description! It might as well be a collection of rocks.
Yes, see OopNotForDomainModeling. Building code objects to model real world things (customers, invoices, trucks) may be ConsideredHarmful even in OOP, despite the fact that these are the most common textbook examples.
The ultimate goal is still a working program. You get sensible answers as soon as you have an idea what that program is supposed to do. Without that information, your tire pressure might as well be a constant defined in module Ford250...
FP is better for modeling transformations on state, not state itself. It is bad for modeling car X. It is better for modeling what happens to car X if it drives Y miles in Z weather condition - where X, Y and Z are all exterior to the program and passed to it as parameters.
Haskell code on FunctionalModelingExamples
I think a specific question you're asking is "How do I implement polymorphism, so that each truck knows how to compute its tire pressure (or whatever). In an OO world, you end up with a set of functions like:
GenericFordTruck.calculateTirePressure(Tire tire) FordF150Truck.calculateTirePressure(Tire tire) TonkaTruck.calculateTirePressure(Tire tire)such that truck.calculateTirePressure(tire) uses polymorphism on the type of truck to determine which method to call.
In most sane functional languages, parametric polymorphism and/or pattern matching can do the same thing for you. You'd have functions defined as:
calculateTirePressure(GenericFordTruck truck, Tire tire) calculateTirePressure(FordF150Truck truck, Tire tire) calculateTirePressure(TonkaTruck truck, Tire tire)Informationally, the two are the same. Its just that most mainstream languages can't handle parametric polymorphism, and force you to use the object.method notation to help the compiler out.
higher order functions can do this (define (calculate-tire-pressure truck tire)) ; it calculates calculates the tire pressure by passing in HoF'sHow is that better than going object.calculateTirePressure(tireId)?
I don't think it's any better - or worse. The differences are in source file organization (probably) and syntax. -- AndrewMccormick
If we have thousands of car models and thousands of operations (check oil, check tires, fill tires, change wipers, etc.), then a RelationalWeenie likely will suggest using a database to track and manage all those. Of course, some of these will share similarities, and that is where the fun begins.
It smells to me like you're trying to force an object mindset.
I just trying to figure out how it works. That can smell however it smells. If you don't know how to do it it's hard to see how you could tell.
How about trying StructureAndInterpretationOfComputerPrograms? There you find how it works.
I don't see any complex examples. It is mostly math related. Look closer! What about the digital circuit simulator and constraint-system? They're beautiful!
Sorry, I see simple things connected simply. I would like a more real-world application so I can see how complex things are modeled and how they interact.
Then you don't understand how complex things are successfully modelled. SICP is great! Simple things connected simply is the right way to build up complex systems. Both the simulator and the constraint systems have complex behaviors, and that's the interesting thing.
Is there a good resource that would introduce FunctionalProgrammingForTheObjectOrientedDeveloper??
I don't think it really has to do with OO. Complex things exist. How do you handle them in a functional language?
Here are some examples based on the code above, written in Haskell: http://kungens.kemi.fi/~shae/src/haskell/Truck.hs -- ShaeErisson
Which functional language are you working with? Baseline SchemeLanguage, for example, provides very little built-in support for creating new data types (as http://www.paulgraham.com/reesoo.html puts it, "all types are in the programmers' heads"). More recent languages (and even not-recent CommonLisp) provide a lot more support for types and what you can do with them. In a PurelyFunctional language, however, you'll have a much more difficult time changing the data in the trucks. This is where ObjectOrientation is a big win over FunctionalOrientation?.
It's easier than you think. In Haskell you use monads (see OnMonads) to make changes, and they end up being pretty much the same thing, with a few different rules. -- ShaeErisson
...which goes back to the question of which functional language you're using. If you're not using Haskell, you may not have an imperative top-level to use to implement the monads.
Impure functional languages, in every case I've seen, means 'allows mutable variables' thereby getting around the 'changing truck data' by just letting you change it (MlLanguage). Part of 'purely functional' seems to be 'allows only single assignment variables' meaning monads are really handy there. Can you tell me of some single assignment languages that do not support monads? -- ShaeErisson
Miranda and Sisal. Whether they count or not any more is an open question. More relevantly, ErlangLanguage is single assignment, but deals with state through the language's concurrency mechanisms.
Actually monads make Haskell an impure language. In fact in a pure functional language it is impossible to even obtain input from the user. If you want to demonstrate that functional programming sucks all you have to do is take a good look at Haskell. Haskell is very nice in a number of respects but when you examine how haskell implements exceptions and other imperative features it becomes obvious that functional languages are seriously limited by not allowing assignment. Monads are more complicated than assignment and they actually make programs less modular because now instead of each object managing its own state data you have this monad which threads state data throughout the program.
In the preceding paragraph there are factual errors in sentences 1,2,4,5.
Monads are purely functional, and they allow you to emulate mutability at the same time. Monads are worth learning, especially since you can use them in any language you want. (I just saw a Perl implementation.) 'Sucks' is an emotional comment, the only response there is that your reasoning sucks because it's emotional. In my opinion, and in my experience (~10 years of OOP, 3 years of FP), monads give significantly more modularity than object oriented practices. Some 'real world' usages of 'not allowing assignment' are the GCC 3.x versions which switched to using 'static single assignment' because it allows the compiler to give better optimizations. -- ShaeErisson
Responding to the original questions:
... the main thing that hit me was that there's no clear way to model real things in the problem space.
Functional programming is not about modeling real things. It is about writing expressions which describe the relationship between things. Also, one tends to model what the program does, not what it does it to.
Let's say I have a car. It has an engine with multiple pistons, it is multiple tires, etc. How would I model this and perform operations in a functional language?
So far, your example only provides concrete data. There is no point, from a functional point of view, in knowing that a car has an engine, pistons and tires. I don't know what your program needs to do.
Using PatternMatching. The operation is a function, to which you pass whatever data it needs to do its work. The function can have several implementations: the one whose pattern matches the passed data is used. For example, suppose the program estimates the time needed for an overhaul (coded in ErlangLanguage):
minutes_for_overhaul(AnyEngine,Pistons) when Pistons > 8 -> minutes_for_overhaul(AnyEngine,8); minutes_for_overhaul(brand_xyz, Pistons) -> 60 + minutes_for_overhaul(any,Pistons); minutes_for_overhaul(_AnyEngine,Pistons) -> 30 * Pistons.(Capitalized arguments are free variables that match on anything. Those beginning with a lowercase are atoms - i.e. symbolic constants - and only match when the function is passed the same exact atom.)
These expressions tell us that:
I would have a data structure with all the parts. It would be a complicated data structure.
No, you probably wouldn't. Passing a huge data structure to a function is not good functional modeling. Pass it only the data it needs, and have it only return useful (usually newly computed) data. This way, your functions are expressing a relationship between things, and don't need to be modified when data evolves. Various higher-level modules, which use this one, can thus store their own data structure, according to what they actually need. Thus there are no unnecessarily complicated data structures.
FunctionalProgramming encourages writing pure, generic functions which allow making decisions at the top level of the call hierarchy. This is the opposite philosophy to ObjectOriented design, which encourages deferring actual behaviour to decisions taken low down by overriding class methods.
Let's say we have a complex representation of a document. In an ObjectOriented solution, we would probably have methods (document.print, document.gatherReferences etc.) to process the document, that recursively call appropriate methods in different parts of the document. In FP, we would most probably have a foldDocument function, to which the operations at different parts of the document are passed as parameters.
See related discussion on ArchitectureAndFunctionalProgramming