27

I just finished reading a book on scala. What strikes me is that every single example in the whole book was numerical in some form or another.

Like a lot of programmers, the only math I use is from discrete and combinatorial mathematics, and usually that's not math I program in an explicit way. I'm really missing some compelling examples of functional alternatives/supplements to regular oo algorithms.

What are some non-numerical use-cases for functional programming ?

pad
  • 41,040
  • 7
  • 92
  • 166
krosenvold
  • 75,535
  • 32
  • 152
  • 208
  • Could you clarify what you mean by "mathematical"? Do you mean "numerical"? – Chris Conway Dec 19 '08 at 18:29
  • Thanks. Yes. That's how much maths I've forgotten since university ;) – krosenvold Dec 19 '08 at 18:39
  • Every single post of this sort is missing the one superset of answers: Data. Functional programming is meant for doing processing of a data set. People confuse this with math a lot because complex math is often applied to datasets. Everyone mentions concurrency, which again is a mechanism for processing a data set. People say parsers, again, processing a dataset. The fact that list comprehensions even exist should be enough to point out, these languages are really completely and entirely built for the purpose of working with data sets. Which are ever growing these days, and why FP matters now. – Jimmy Hoffa Aug 21 '12 at 20:14
  • Check out [Text Processing in Python](http://www.amazon.com/gp/product/0321112547?ie=UTF8&tag=theende-20&linkCode=xm2&camp=1789&creativeASIN=0321112547). The book starts out with some simple but well-motivated examples where functional programming techniques make code easier to read and more likely to be correct. – John D. Cook Dec 19 '08 at 18:12

16 Answers16

50

My company asked me to write a custom application that allowed users to perform ad hoc queries against a flat-file database. The users of this app were your typical Joe Businessman types. They are not programmers, and its unlikely they have ever seen an SQL statement in their lives.

As a result, I was tasked to develop a friendly userinterface that would allow users to select columns, tables, conditions, etc to build up a query. This is challenging because I can represent the SQL statement in the UI without first creating an abstract representation of it in memory.

The first iteration was written in C#. I created a boatload classes to represent the abstract syntax of an SQL statement, which resulted in a really cumbersome object model:

  • a Join class, a Joins collection class
  • a WhereClause class, a WhereClauses collection class
  • a SelectedColumn class, SelectedColumns collection class
  • an OrderBy class, OrderBy collection collections class
  • an SqlStatement class that grouped all of the aforemtioned classes together

Converting an SqlStatement instance to a string was gloriously painful, ugly, and buggy. Moving the oppositive direction, from string to SqlStatement, was even worse, as it broke apart the pieces of an SQL string using lots of regex and string manipulation.

I hacked together the system, produced an application that worked, but I wasn't very happy with it. I especially wasn't happen when the business requirements of the app changed on me, which forced me to revisit my C# code.

Just as an experiment, I rewrote my SqlStatement in F# and represented it as a union:


type dir = Asc | Desc
type op = Eq | Gt | Gte | Lt | Lte
type join = Inner | Left | Right

type sqlStatement =
    | SelectedColumns of string list
    | Joins of (string * join) list
    | Wheres of (string * op * string) list
    | OrderBys of (string * dir) list

type query = SelectedColumns * Joins * Wheres * OrderBys

That small amount of code replaced a few hundred lines of C# and a dozen or so classes. More importantly, pattern matching simplified the process required to convert abstract representation into an SQL string.

The fun part was converting an SQL string back into a query object using fslex/fsyacc.

If I remember correctly, the original C# code totalled 600 lines and around a dozen classes, lots of messy regex, and requied two days to write and test. By comparison, the F# code consisted of one .fs file of around 40 lines, 100 lines or so to implement the lexer/parser, and consumed a few hours out of my day to test.

Seriously, writing this part of the app in F# felt like cheating, that's how trivially easy it was.

Juliet
  • 80,494
  • 45
  • 196
  • 228
10

We used Haskell to implement a domain-specific language for describing, pricing, and monitoring exotic derivatives.

Diomidis Spinellis
  • 18,734
  • 5
  • 61
  • 83
7

Functional programming is a paradigm like procedural/structured, object-oriented, and generic/templated programming are. It's turing-complete so you can do anything you want.

Aside from math and science, it's makes it easier for parser combinators, artifical intelligence, concurrency, dynamic evaluation, co-routines, continuations, terse notation (faster brain-to-keyboard-to-text-file cycle and less code to maintain), strongly-typed parametization (see Haskell's algebraic types) and dynamic self-reflection (e.g., minimalistic metacircular interpreters with a REPL).

Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
5

Got another one for you:

I'm involved in the very early stages of prototyping a suite of new enterprise-scale financial products intended for small-to-medium sized banks, local government, stock exchanges, etc. You're probably thinking "oh, financial code, you must be doing a lot of math" -- actually, no. These products are intended to be highly customizable and allow users to inject business rules at strategic points in the application.

We're using F# to represent and interpret business rules. To use a naive example, lets we're writing some code for check processing, we might write the rules like this:

type condition =
    | Test of string
    | And of condition * condition
    | Or of condition * condition
    | Not of condition

type transactionWorkflow =
    | Reject
    | Approve
    | AdministratorOverride of string
    | If of condition * transactionWorkflow list
         (* condition,  true condition *)
    | IfElse of condition * transactionWorkflow list * transactionWorkflow list
         (* condition,      true condition,            false condition *)
    | AttachForms of string list

Using a special application, users can write some business rules represented by the structure above. For example:

let checkProcessingWorkflow =
    [If(Test("account doesn't exist")
        ,[AdministratorOverride("Account doesn't exist. Continue?");
          AttachForms ["40808A - Null Account Deposit"]]
       );
     If(Test("deposit > 10000")
        ,[
            If(And(Test("account created within 3 months")
                   ,Test("out of country check"))
               ,[Reject]);
            IfElse(Test("account state = TX")
                    ,[AttachForms ["16A"; "16B"]]
                    ,[AttachForms ["1018"]]
                 )
         ]
       );
     Approve
    ]

So, rather than writing one business-rules engine to rule them all, we handle certain processes as a very tiny domain-specific language intepreted by F#. I'm hoping this approach will allow us to design very simple business-readable DSLs without needed to detect conflicting rules.

Of course, everything above is just concept-code, and we're still in the very earlier stages of even prototyping one of our rules system. We're using F# rather than Java or C# for one particular reason: pattern matching.

Juliet
  • 80,494
  • 45
  • 196
  • 228
3

"Getting Started with Erlang" has an extensive client/server example (starting in Section 1.3.5) which may suit your needs.

Chris Conway
  • 55,321
  • 43
  • 129
  • 155
3

The more I use a functional style, the better I like it. Consider this Python fragment from another question:

>>> testlist
[1, 2, 3, 5, 3, 1, 2, 1, 6]
>>> [i for i,x in enumerate(testlist) if x == 1]
[0, 5, 7]

This is admittedly a more or less mathematical statement, but there are lots of generators in Python. Once you get used to it, using a list comprehension in place of a loop is both easy to understand, and less likely to have a bug (you don't get "off by one" bugs.)

Community
  • 1
  • 1
Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • What do you mean "lots of generators"? They are a language feature and you can write an infinite amount of generators, just like you can generate an infinite amount of different for loops. – Vinko Vrsalovic Dec 19 '08 at 19:13
  • I think you could do [line for line in file.readlines()] too, but I'm not positive and didn't want to try it, I'm busy this morning. – Charlie Martin Dec 19 '08 at 19:14
  • Vinko, I mean "lots of generators built in" but of course you can always write one too. – Charlie Martin Dec 19 '08 at 19:14
2

These days, I wouldn't even consider writing a DSL lexer/parser in a non-functional language (in broad sense of the term). ADTs and pattern matching make it so much easier.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
2

Really interesting question because I thought I was the only author writing books on functional programming for numerics!

Functional programming has historically been far more commonly used for metaprogramming, meaning writing programs that manipulate other programs. This includes interpreters and compilers (e.g. for DSLs) as well as more esoteric applications such as theorem provers (Coq, Isabelle) and term rewrite systems (e.g. computer algebra systems like Mathematica). The Meta Language (ML) family of languages were specifically designed for this.

J D
  • 48,105
  • 13
  • 171
  • 274
2

It's true that many books on functional programming uses "numerical programming" to teach, but there are exceptions.

Haskell School of Expression is a beginner's book on Haskell that uses multimedia as its vehicle for teaching.

Real World Haskell doesn't really have any particular vehicle throughout the entire book, but there are several chapters covering writing "real" programs in a functional style.

Magnus
  • 4,644
  • 1
  • 33
  • 49
1

for those who consider LISP a functional programming language, there's a http server written in common lisp out there, introduced in a 1994 paper and still being developed in 2006:

for more modern stuff, you might want to ask google "haskell web server", you will probably find a few interesting examples. one lead me find this site: http://code.haskell.org/.

mariotomo
  • 9,438
  • 8
  • 47
  • 66
1

Ted Neward wrote a 10 part article on Scala, aimed at Java programmers, and the series finished off with writing a DSL in Scala. This particular DSL is actually a numeric calculator, but that's not what's interesting about it, it's the way the DSL can be easily assembled in a functional language

Part1

Part2

Part3

skaffman
  • 398,947
  • 96
  • 818
  • 769
1

Pattern matching is also a place where functional programming shines, making it really useful in areas such as Bioinformatics.

However, given great compilers we have today, functional programming shines nearly everywhere.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • Although pattern matching correlates with functional programming they are not actually directly related. In particular, many functional languages have little or no support for pattern matching: Lisp, Scheme, Erlang, C# etc. – J D Jul 01 '10 at 20:58
  • 1
    @Jon: [Erlang Pattern Matching](http://www.erlang.org/doc/reference_manual/patterns.html "Erlang Pattern Matching") – Andriy Tylychko Feb 02 '11 at 16:53
  • Sorry, I should have been more specific. Scheme also has another form of pattern matching. I was referring, as I assume Mehrdad was, to ML-style pattern matching over algebraic datatypes. – J D Feb 02 '11 at 20:58
1

Check "Purely functional data structures" (and here's the PhD thesis that inspired the book).

They show how you can create standard data structures in purely functional (no side-effects) languages. You can then use them to program anything.

Disclaimer: I'm pulling an Atwood here, I've barely read a couple of reviews of the book and skimmed over the thesis, it's on my toread list.

Vinko Vrsalovic
  • 330,807
  • 53
  • 334
  • 373
  • Great book, though not an easy read. The thesis is pretty much unreadable IMHO. – Paul Dec 19 '08 at 18:56
  • I preferred the book too, the thesis is not nearly as helpful. – boutta Jul 15 '09 at 08:24
  • I found both readable and academically fascinating but totally useless in the real world. – J D Jul 01 '10 at 21:37
  • @Jon: Why? The data structures seem totally usable if you are actually working in a programming language where the structures are writable – Vinko Vrsalovic Jul 02 '10 at 08:37
  • They are certainly usable in that they work but they solve problems I do not have and exacerbate the problems that I do have. When do you need a queue that offers persistence but poor performance and poor scalability, for example? For that matter, when will you ever want thread-safety and poor performance at the same time? – J D Jul 02 '10 at 19:59
1

Bridging the algorithm gap: A linear-time functional program for paragraph formatting (1997)
by Oege De Moor, Jeremy Gibbons
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.33.7923

Structuring Graphical Paradigms in TkGofer (1997) by Koen Claessen, Ton Vullinghs, Erik Meijer http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.5525

Modelling office processes with functional parsers (1994) by Gert Florijn
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.1307

ja.
  • 4,245
  • 20
  • 22
1

The best specific example I can give is StringTemplate, a templating engine used (among many other places) in the ANTLR parser generator.

In one paper on the design and development of StringTemplate, Terence Parr wrote that he was originally skeptical of functional programming, and so laughed out loud at himself when he realized that StringTemplate was essentially a functional language for generating text.

joel.neely
  • 30,725
  • 9
  • 56
  • 64
0

LINQ takes a lot of cues from functional programming. Taking a look at how an arbitrary LINQ provider is implemented might provide you with some practical insight.

Gabriel Isenberg
  • 25,869
  • 4
  • 37
  • 58