How do you design a functional program? [closed] - f#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
From day 1 of my programming career, I started with object-oriented programming. However, I'm interested in learning other paradigms (something which I've said here on SO a number of times is a good thing, but I haven't had the time to do). I think I'm not only ready, but have the time, so I'll be starting functional programming with F#.
However, I'm not sure how to structure much less design applications. I'm used to the one-class-per-file and class-noun/function-verb ideas in OO programming. How do you design and structure functional applications?

Read the SICP.
Also, there is a PDF Version available.

You might want to check out a recent blog entry of mine: How does functional programming affect the structure of your code?
At a high level, an OO design methodology is still quite useful for structuring an F# program, but you'll find this breaking down (more exceptions to the rule) as you get down to lower levels. At a physical level, "one class per file" will not work in all cases, as mutually recursive types need to be defined in the same file (type Class1 = ... and Class2 = ...), and a bit of your code may reside in "free" functions not bound to a particular class (this is what F# "module"s are good for). The file-ordering constraints in F# will also force you to think critically about the dependencies among types in your program; this is a double-edged sword, as it may take more work/thought to untangle high-level dependencies, but will yield programs that are organized in a way that always makes them approachable (as the most primitive entities always come first and you can always read a program from 'top to bottom' and have new things introduced one-by-one, rather than just start looking a directory full of files of code and not know 'where to start').

How to Design Programs is all about this (at tiresome length, using Scheme instead of F#, but the principles carry over). Briefly, your code mirrors your datatypes; this idea goes back to old-fashioned "structured programming", only functional programming is more explicit about it, and with fancier datatypes.

Given that modern functional languages (i.e. not lisps) by default use early-bound polymorphic functions (efficiently), and that object-orientation is just a particular way of arranging to have polymorphic functions, it's not really very different, if you know how to design properly encapsulated classes.
Lisps use late-binding to achieve a similar effect. To be honest, there's not much difference, except that you don't explictly declare the structure of types.
If you've programmed extensively with C++ template functions, then you probably have an idea already.
In any case, the answer is small "classes" and instead of modifying internal state, you have to return a new version with different state.

F# provides the conventional OO approachs for large-scale structured programming (e.g. interfaces) and does not attempt to provide the experimental approaches pioneered in languages like OCaml (e.g. functors).
Consequently, the large-scale structuring of F# programs is essentially the same as that of C# programs.

Functional programming is a different paradigm for sure. Perhaps the easiest way to wrap your head around it is to insist that the design be laid out using a flow chart. Each function is distinct, no inheritance, no polymorphism, distinct. The data is passed around from function to function to make deletions, updates, insertion, and create new data.

On structuring functional programs:
While OO languages structure the code with classes, functional languages structure it with modules. Objects contain state and methods, modules contain data types and functions. In both cases the structural units group data types together with related behavior. Both paradigms have tools for building and enforcing abstraction barriers.
I would highly recommend picking a functional programming language you are comfortable with (F#, OCaml, Haskell, or Scheme) and taking a long look at how its standard library is structured.
Compare, for example, the OCaml Stack module with System.Collections.Generic.Stack from .NET or a similar collection in Java.

It is all about pure functions and how to compose them to build larger abstractions. This is actually a hard problem for which a robust mathematical background is needed. Luckily, there are several patterns with deep formal and practical research available. On Functional and Reactive Domain Modeling Debasish Ghosh explores this topic further and puts together several practical scenarios applying pure functional patterns:
Functional and Reactive Domain Modeling teaches you how to think of
the domain model in terms of pure functions and how to compose them to
build larger abstractions. You will start with the basics of
functional programming and gradually progress to the advanced concepts
and patterns that you need to know to implement complex domain models.
The book demonstrates how advanced FP patterns like algebraic data
types, typeclass based design, and isolation of side-effects can make
your model compose for readability and verifiability.

Related

Approach to designing large functional programs

I've been reading lots on functional languages and would like to maybe play with re-writing some parts of my application in F#. Is it better to design from the outside in or the inside out?
One of the influental works on the subject of FP Why Functional Programming Matters by John Hughes can be considered as a direct answer:
Our ability to decompose
a problem into parts depends directly on our ability to glue solutions
together. To support modular programming, a language must provide good
glue. Functional programming languages provide two new kinds of glue —
higher-order functions and lazy evaluation. Using these glues one can modularize
programs in new and useful ways, and we’ve shown several examples of this.
Smaller and more general modules can be reused more widely, easing subsequent
programming. This explains why functional programs are so much smaller and
easier to write than conventional ones. It also provides a target for functional
programmers to aim at. If any part of a program is messy or complicated, the
programmer should attempt to modularize it and to generalize the parts. He or
she should expect to use higher-order functions and lazy evaluation as the tools
for doing this.
I would also recommend looking at contemporary interview with John Hughes in InfoQ.
One article that really helped me come to terms with functional programming is this one:
http://prog21.dadgum.com/23.html
It is a tutorial for how to create a Pac-Man clone using functional-programming techniques. I don't even recognize the language he used (it might have been Erlang,) but the explanation helped me understand the correct mindset which I used when rewriting one of my programs in Scheme.
I'm not an expert at all on this subject, but here is a link to an article on this subject, by 'our' very own Brian:
How does functional programming affect the structure of your code?
And some questions from SO & Programmers (where - incidentally - I suspect this question would be a better fit)
Real world pitfalls of introducing F# into a large codebase and engineering team
How to organize F# source of large project (>300 classes) in Visual Studio?
Not sure I understand what is meant by "inside out" / "outside in", but FP is most useful "in the small" -- at the function level. OO is probably still the best way to organize projects in the large. It's easiest to deal with objects that correlate with your business domain.
I guess by outside in you mean top to bottom approach and by inside out you mean from bottom to top. If this is what you mean than FP is more suited towards bottom up approach i.e inside out.
While designing FP programs think about solving the problem using:
Data Structure : What all data your application needs to handle and
which data structure is most suitable to represent that data.
Function : A function does one thing (and do it correctly).
Composition : Create new functions which achieve their goals by composing other functions using technique like higher order functions and compositions.
Other more advance and abstract FP techniques like Monads etc.
So basically you start from bottom, for each atomic problem you write a function and then as you move upward in the design you use these atomic function to create functions at higher level using composition.
Remember always think of solving problem using abstractions and composition of those abstraction rather than thinking sequentially as you would do in a imperative programming.

What are the benefits of using Objects in a functional programming language?

What would be a valid reason(s) to use objects in functional programming languages? I see that f# is a functional programming language that lends heavily on the object side when dealing with the .net ecosystem of classes. But apart from this interaction with other assemblies/programs maybe written in c#, why would anyone choose to use objects for decomposition of a program in a function oriented language or style?
Does mixing up a style of program prove a help or a hindrance?
Functional and object oriented designs make different types of extensions easy. Given a discriminated union in a functional setting, it's easy to define any number of functions which work on that type, but it's hard to add additional cases to the type, since that would require going back to add the additional case to each function which pattern matches on the type. On the other hand, given a base type (or interface) an OO setting, it's easy to add new subtypes, but adding new operations to the base type is hard, since it potentially requires modifying existing subtypes to add an implementation of the new operation to each one.
Depending on the type of extensibility that's most relevant to the task at hand, either the functional or the object oriented approach may make more sense, so it's nice to have both options available. One popular approach is to use a functional approach "in the small" and an OO approach "in the large" (e.g. it's mentioned in this podcast with Luke Hoban).
Objects provide encapsulation that makes large-scale programming easier.
What would be a valid reason(s) to use objects in functional programming languages?
Objects are used in functional languages for a variety of reasons:
Large-scale structuring of programs.
Interoperability with existing OOP code (e.g. on the JVM or CLR).
Problems for which the ability to extend class hierarchies with more classes is a natural fit.
Does mixing up a style of program prove a help or a hindrance?
Can be a help but it would not be a good idea to do it without good reason.

Why do Ruby developers appear not to use UML?

I always hear about UML being used in Java projects but never in Ruby ones. Is this just a cultural difference or is there less of a need for modeling in Ruby development because it's part of a more 'agile' culture?
Obviously you can't generalize this to everybody, but programmers in languages like Ruby and Python tend to be less drawn to large design documents and UML because they view their language of choice as being concise and expressive enough that it isn't always necessary. There's a feeling of, "I could spend time and plot all this out in UML...or I could just write some Python that actually implements the design and expresses it in a language I like to read and lots of people can read." Java programs tend to feel "heavier" than their Ruby or Python counterparts — it's part of the design of the language.
Note that I'm not saying this is true of your project or even that it's true at all as a whole — this is just what I've observed about these programming cultures.
Call me crazy but UML isn't for me regardless of the application stack.
(Note, tongue sometimes placed in cheek.)
Probably one of the biggest cultural differences is that Java is often used in projects with large numbers of programmers, led by PHBs, where the high-level system design is done by people with the title "software architect". On these sort of projects the people in the "software architect" role will often generate a large amount of documentation (including UML relationship and state diagrams) during the initial planning phase of the project. These and other documentation artifacts are then expected to be implemented by the hordes of non-architect-programmers.
Ruby on the other hand, is the new hotness and is therefore more often chosen by people who want to program in it. Since the "architect" is the implementer, there is less need for complex upfront documentation. The implementers jot a few notes on general design guidelines and then sit down to program rather than designing upfront for others to program.
This isn't to say that you won't find a few scattered UML diagrams here or there in projects built in Ruby or other snazzy languages -- such as when someone is trying to describe a complex concept -- but such things just aren't needed as much if you are doing the work yourself.
One of the obvious reasons is that well-designed Ruby programs rely heavily on Mixins, which AFAIK simply cannot be modeled in UML at all. I know that Schärli et al developed an extension to UML that can represent Traits which given the close relationship between Traits and Mixins could probably be adapted or just reused for representing Mixins, but then it's not UML anymore.
This is a comment to the answer about mixins. Mixins can actually be modelled in UML quite easily using many different methods. Typically one uses multiple inheritance, interfaces or stereotypes (or any combination of these). Choosing the method depends on the project and personal taste - let us not forget that the main reason for modeling is to conquer complexity, better understand reality and communicate more effectively so each model needs to fit a particular problem and audience. Models are, by definition, pragmatic and so must be the process of creating them.
Let us not forget that UML is extensible using profiles and stereotypes. Such extended UML is still valid UML.
In general, UML is more expressive and less restrictive than programming languages so if something can be written down in some programming language, it can also be done in UML.

How does "Language Oriented Programming" compare to OOP/Functional in the real world

I recently began to read some F# related literature, speaking of "Real World Functional Programming" and "Expert F#" e. g.. At the beginning it's easy, because I have some background in Haskell, and know C#. But when it comes to "Language Oriented Programming" I just don't get it. - I read some explanations and it's like reading an academic paper that gets more abstract and strange with every sentence.
Does anybody have an easy example for that kind of stuff and how it compares to existing paradigms? It's not just academic fantasy, isn't it? ;)
Thanks,
wishi
Language oriented program (LOP) can be used to describe any of the following.
Creating an external language (DSL)
This is perhaps the most common use of LOP, and is where you have a specific domain - such as UPS shipping packages via transit types through routes, etc. Rather than try to encode all of these domain-specific entities inside of program code, you rather create a separate programming language for just that domain. So you can encode your problem in a separate, external language.
Creating an internal language
Sometimes you want your program code to look less like 'code' and map more closely to the problem domain. That is, have the code 'read more naturally'. A fluent interface is an example of this: Fluent Interface. Also, F# has Active Patterns which support this quite well.
I wrote a blog post on LOP a while back that provides some code examples.
F# has a few mechanisms for doing programming in a style one might call "language-oriented".
First, the syntax niceties (function calls don't need parentheses, can define own infix operators, ...) make it so that many user-defined libraries have the appearance of embedded DSLs.
Second, the F# "quotations" mechanism can enable you to quote code and then run it with an alternative semantics/evaluation engine.
Third, F# "computation expressions" (aka workflows, monads, ...) also provide a way to provide a type of alternative semantics for certain blocks of code.
All of these kinda fall into the EDSL category.
In Object Oriented Programming, you try to model a problem using Objects. You can then connect those Objects together to perform functions...and in the end solve the original problem.
In Language Oriented Programming, rather than use an existing Object Oriented or Functional Programming Language, you design a new Domain Specific Language that is best suited to efficiently solve your problem.
The term language Oriented Programming may be overloaded in that it might have different meanings to different people.
But in terms of how I've used it, it means that you create a DSL(http://en.wikipedia.org/wiki/Domain_Specific_Language) before you start to solve your problem.
Once your DSL is created you would then write your program in terms of the DSL.
The idea being that your DSL is more suited to expressing the problem than a General purpose language would be.
Some examples would be the make file syntax or Ruby on Rails ActiveRecord class.
I haven't directly used language oriented programming in real-world situations (creating an actual language), but it is useful to think about and helps design better domain-driven objects.
In a sense, any real-world development in Lisp or Scheme can be considered "language-oriented," since you are developing the "language" of your application and its abstract tree as you code along. Cucumber is another real-world example I've heard about.
Please note that there are some problems to this approach (and any domain-driven approach) in real-world development. One major problem that I've dealt with before is mismatch between the logic that makes sense in the domain and the logic that makes sense in software. Domain (business) logic can be extremely convoluted and senseless - and causes domain models to break down.
An easy example of a domain-specific language, mentioned here, is SQL. Also: UNIX shell scripts.
Of course, if you are doing a lot of basic ops and have a lot of overlap with the underlying language, it is probably overengineering.

If you already know LISP, why would you also want to learn F#?

What is the added value for learning F# when you are already familiar with LISP?
Static typing (with type inference)
Algebraic data types
Pattern matching
Extensible pattern matching with active patterns.
Currying (with a nice syntax)
Monadic programming, called 'workflows', provides a nice way to do asynchronous programming.
A lot of these are relatively recent developments in the programming language world. This is something you'll see in F# that you won't in Lisp, especially Common Lisp, because the F# standard is still under development. As a result, you'll find there is a quite a bit to learn. Of course things like ADTs, pattern matching, monads and currying can be built as a library in Lisp, but it's nicer to learn how to use them in a language where they are conveniently built-in.
The biggest advantage of learning F# for real-world use is its integration with .NET.
Comparing Lisp directly to F# isn't really fair, because at the end of the day with enough time you could write the same app in either language.
However, you should learn F# for the same reasons that a C# or Java developer should learn it - because it allows functional programming on the .NET platform. I'm not 100% familiar with Lisp, but I assume it has some of the same problems as OCaml in that there isn't stellar library support. How do you do Database access in Lisp? What about high-performance graphics?
If you want to learn more about 'Why .NET', check out this SO question.
If you knew F# and Lisp, you'd find this a rather strange question to ask.
As others have pointed out, Lisp is dynamically typed. More importantly, the unique feature of Lisp is that it's homoiconic: Lisp code is a fundamental Lisp data type (a list). The macro system takes advantage of that by letting you write code which executes at compile-time and modifies other code.
F# has nothing like this - it's a statically typed language which borrows a lot of ideas from ML and Haskell, and runs it on .NET
What you are asking is akin to "Why do I need to learn to use a spoon if I know how to use a fork?"
Given that LISP is dynamically typed and F# is statically typed, I find such comparisons strange.
If I were switching from Lisp to F#, it would be solely because I had a task on my hands that hugely benefitted from some .NET-only library.
But I don't, so I'm not.
Money. F# code is already more valuable than Lisp code and this gap will widen very rapidly as F# sees widespread adoption.
In other words, you have a much better chance of earning a stable income using F# than using Lisp.
Cheers,
Jon Harrop.
F# is a very different language compared to most Lisp dialects. So F# gives you a very different angle of programming - an angle that you won't learn from Lisp. Most Lisp dialects are best used for incremental, interactive development of symbolic software. At the same time most Lisp dialects are not Functional Programming Languages, but more like multi-paradigm languages - with different dialects placing different weight on supporting FPL features (free of side effects, immutable data structures, algebraic data types, ...). Thus most Lisp dialects either lack static typing or don't put much emphasis on it.
So, if you know some Lisp dialect, then learning F# can make a lot of sense. Just don't think that much of your Lisp knowledge applies to F#, since F# is a very different language. As much as an imperative programming used to C or Java needs to unlearn some ideas when learning Lisp, one also needs to unlearn Lisp habits (no types, side effects, macros, ...) when using F#. F# is also driven by Microsoft and taking advantage of the .net framework.
F# has the benefit that .NET development (in general) is very widely adopted, easily available, and more mass market.
If you want to code F#, you can get Visual Studio, which many developers will already have...as opposed to getting the LISP environment up and running.
Additionally, existing .NET developers are much more likely to look at F# than LISP, if that means anything to you.
(This is coming from a .NET developer who coded, and loved, LISP, while in college).
I'm not sure if you would? If you find F# interesting that would be a reason. If you work requires it, it would be a reason. If you think it would make you more productive or bring you added value over your current knowledge, that would be a reason.
But if you don't find F# interesting, your work doesn't require it and you don't think it would make you more productive or bring you added value, then why would you?
If the question on the other hand is what F# gives that lisp don't, then type inference, pattern matching and integration with the rest of the .NET framework should be considered.
I know this thread is old but since I stumbled on this one I just wanted to comment on my reasons. I am learning F# simply for professional opportunities since .NET carries a lot of weight in a category of companies that dominate my field. The functional paradigm has been growing in use among more quantitatively and data oriented companies and I'd like to be one of the early comers to this trend. Currently there doesn't an exist a strong functional language that fully and safely integrates with the .NET library. I actually attempted to port some .NET from Lisp code and it's really a pain b/c the FFI only supports C primitives and .NET interoperability requires an 'interface' construct and even though I know how to do this in C it's really a huge pain. It would be really, really, good if Lisp went the extra mile in it's next standard and required a c++ class (including virtual functions w/ vtables), and a C# style interface type in it's FFI. Maybe even throw in a Java interface style type too. This would allow complete interoperability with the .NET library and make Lisp a strong contender as a large-scale language. However with that said, coming from a Lisp background made learning F# rather easy. And I like how F# has gone the extra mile to provide types that you would commonly see it quantitative type work. I believe F# was created with mathematical work in mind and that in itself has value over Lisp.
One way to look at this (the original question) is to match up the language (and associated tools and platforms) to the immediate task. If the task requires an overwhelming percentage of .NET code, and it would require less shoe-horning in one language than another to meet the task head-on, then take the path of least resistance (F#). If you don't need .NET capabilities, and you're comfortable working with LISP and there's no arm-bending to move away from it, keep using it.
Not really much different from comparing a hammer with a wrench. Pick the tool that fits the job most effectively. Trying to pick a tool that's objectively "best" is nonsense. And in any case, in 20 years, all of the currently "hot" languages might be outdated anyway.

Resources