Hacker News new | past | comments | ask | show | jobs | submit login
Functional programming for Object Oriented programmers (lifebeyondfife.com)
75 points by lifebeyondfife on Nov 24, 2011 | hide | past | favorite | 34 comments



My problem with these things (and I'm not picking on this particular article, just on introduction to functional programming articles in general) is that they always tell you how awesomely easy it is to make lists, or calculate the fibonacci sequence, two things I never have to do in the office.

What I want to know is whether functional programming languages would help me to write UIs better than C# does, to create XML documents from data, to retrieve data from web APIs and then display the results, etc.

These are things I have a need to do on a daily basis, and I'd like to know if F# is the tool for them, or if I should stick to C# unless I'm writing a list processor or calculation engine.


Fibonacci is basically the "Hello, World" program of functional programming--it's trivial but succinctly summarizes several disparate language features. The reason you see it so often is that you are (naturally) reading introductory articles. I imagine if you didn't know anything about imperative programming, the endless stream of "Hello, World" and contrived OO examples (Dog is an Animal...) would also seem onerous.

Lists, on the other hand, are actually very useful in functional programming. Lists and their corresponding higher-order functions are the equivalent of loops in imperative languages.

The real issue you're seeing, though, is that you have to start small to understand everything. This is true of everything, not just functional programming. I remember learning C++ and being really frustrated that all I ever wrote were silly command-line programs; however, I could hardly have jumped into UI development with practically no understanding of the language.

However, most practical applications require you understand the very basics: recursion, list operations, types... An article that just jumped into something like FRP (Functional Reactive Programming, a really awesome approach to making UIs) would just confuse you unless you've spent at least a little bit of time with Fibonacci and friends.

Ultimately, the only way to know if functional programming is better for some problem you have is to first understand its fundamental building blocks.


> Ultimately, the only way to know if functional programming is better for some problem you have is to first understand its fundamental building blocks.

Without understanding anything about event loops or closures, you can look at http://www.nodejs.org and think "hey wow, that looks just like what I need!"

Why can't the same hold about programming languages? Why do the functional programming aficionados insist that I get all turned on by a quicksort before telling me how immutability with remove all my multithreading headaches?

I mean, F# for example, has a communication system (Agents) which I find really gorgeous on first glance. These help solve real problems, and can do something you can't really do well in C#.


I think the main difference is in scope: to use node, you basically write code as you normally would in JavaScript, which is not entirely dissimilar to languages almost everybody is familiar with. It is different, but not by much. Writing a program, particularly anything interesting, in a language like Haskell is entirely dissimilar from anything most people have used. F# is probably also like this, but I'm not familiar enough with it to be sure.

The point of trivial examples like quicksort is just to illustrate the fundamental differences--mostly advantages--of using functional languages. Using a functional language will change every aspect of your code, so even examples like this are illustrative while being simple enough to fade into the background.

Languages like Haskell do have a ton of cool features, but they are all overshadows by how different they are. Once the fundamental differences are thoroughly explained, other goodies can emerge. For example, look at snap, a really fast web framework for Haskell. It's even faster than node.


I was a C# programmer for several years, and I've been writing F# full time now for a little over a year. To briefly answer your points:

- F# doesn't have tool support for _building_ UIs (e.g., Winforms designer), but beyond that, it's very good for the code which actually runs the UI (the eventing and so forth).

- You could build some functions to manipulate fragments from XML, then build some higher-level functions from those, etc., then traverse your data (whatever it is) and use the functions you've built to emit XML in a clean and _precise_ way. I think Haskell already has such a library -- perhaps someone's ported it to F#?

- You can use F# 'async' workflows to retrieve data from web APIs really easily (and quickly, if you are doing it in bulk). In fact, this is probably one of the most common code examples shown for async workflows.

In my experience, F# isn't great at everything, but in general, I'm much, much more productive writing F# than I ever was/am in C#.


>You could build some functions to manipulate fragments from XML, then build some higher-level functions from those, etc., then traverse your data (whatever it is) and use the functions you've built to emit XML in a clean and _precise_ way. I think Haskell already has such a library -- perhaps someone's ported it to F#?

Are you talking about Parser combinators? haskell [http://www.haskell.org/haskellwiki/Parsec] and F#'s FParsec [http://www.quanttec.com/fparsec/]?


Can you share some experiences with F# in bigger projects? I'm a little bit worried about the accessibility of larger code bases with global type inference. I would say that I have a pretty good grasp of the language in general, but I usually feel lost without IDE support or comments because heavy usage of things like currying and type inference assures that the signature of a function is pretty meaningless.


Currying and type inference do not make function signatures meaningless, unfortunately however, reading their types is a skill that you need to practice for it to become natural.

As for global type inference the one in F# is only partially global (between Scala and ML , Haskell). Anytime you are dealing with ad-hoc polymorphism, even when F# has inferred the types, you will often have to put the type in. Full point free programming also does not always resolve if you are into that.

I have gotten into the habit of putting types and names for complicated functions in comments (///). I also write short descriptions for particularly dense pieces of code and have gotten in the habit of writing clearer, less dense code with full names because otherwise it does take longer to mentally unpack. That is, functional languages make it easy to write stuff like: let wu wp wn nu y x = wp * (exp (nu * y * x)) , wn * (exp (-nu * y * x))


I can't really speak from any experience as I've only just started programming in F# myself, I think for the most part it's not meant to replace the things you mention. The reason I looked into it initially was because of its applicability with mathematical calculations and parallelism. Because of the .Net angle though you can mix and match your projects on Windows systems. Here's a Stack Exchange question about what proficient F# programmers use it for: http://stackoverflow.com/questions/568827/what-areas-of-code...


Something to keep in mind is that you can make your C# surprisingly functional using LINQ. It's inspired by Haskell and functional programming. It makes the transition from "imperative with functional features" to "functional" very simple.

And you can use Reactive Extensions in C#, which is the most accessible framework for FRP (functional reactive programming) out there and very useful for UI and asynchronous tasks. I've just started exploring it, but it's pretty fun so far.


There are some books that go over using functional programming for "real world" tasks. Two off of the top of my head are Real-World Functional Programming by Tomas Petricek and Jon Skeet (.NET focused, and might be a bit aged now), and Real World Haskell (http://book.realworldhaskell.org/). So indeed, there are resources to help answer this question by walking you through common things like drawing graphs, database querying, working with XML, etc.

I've given F# a try recently for some of those tasks, and while it certainly is very capable of accomplishing them, I've found that using the .NET libraries, or having to expose my own APIs to C# developers in a way that will be natural to them, often leads me to simply writing C# with F#'s syntax. This is certainly no worse than having done so in C# directly, but the core ideas behind functional programming just seem to get diluted. On a side note, I think that with a bit of more design in mind, it should be possible to at least keep the core components 'functional' and then just have a middle layer that defines the classes and handles interop so your code can then be used from C# in an OO way.


Can you give an example? I have found this is only the case in a small part to do with initializing the structure. Working with Active patterns and monads can turn OO code more functional.

As for exposing I write in a typical functional ways then provide wrappers. But these days even non wrapped code can be trivially consumed from C#.


My most recent "meh" styled F# script had to parse 16MB of ugly XML that contained values which even unicode did not define. The goal was to create a lookup structure based on this data that could then be used from C#. I used seq expressions for cleaning up the input stream, active patterns for parsing the XML, but felt that I had no other choice than to use classes with dictionary members for the lookup data structure. With well over 100,000 items to organize and store, I did not want the overhead of creating a functional structure that would then have to be converted to nested Dictionaries for C# use. Anyway, at that point it became kind of pointless to try and avoid an imperative approach to populating the data structure.


I am not quite sure you don't make lists on a daily basis. I do it all the time when I program -- and I would guess that most people do so too.

Calculating the Fibonnaci sequence is really not that interesting, true enough, but it serves as a relatively simple way to demonstrate recursion (please don't claim you never use it, it is just masked as loops in C#).

I find it funny that you want to retrieve data from web APIs and create XML ducuments -- which is a case where you would often use lists (e.g an XML document is essentially a tree which is just a list of trees and nodes) -- so any language which makes it easy to process list would make you more productive in solving exactly the problems you want it to, if only you would learn it.


We use libraries to handle XML itself, and convert it to objects, so that we get compile errors when schemas change and know what code has to change to match it.

If we were DOM-walking or similar then I can totally see where functional code would come in useful (LINQ being a halfway house in that respect).


In F# it's super easy to deal with the XML stream itself. Define all the records for the stuff you want to deal with and iterate over the stream with a match statement that invokes read(). You can further abstract the code by making it work with a map that maps element names to parsing functions.

eg.

  type BookXml =
    | Author of { Name: string }
    | Book of { Author: Author ; Title : string }
    | Document of Seq<BookXML>

  let readAuthor (xml:XmlTextReader) : BookXml =
    { Name: xml.ReadContentAsString() }

  let readBook (xml:XmlTextReader) : BookXml =
     { Author = readAuthor(xml); Title = xml.ReadContentAsString() }
  
  let parse xml = 
    match (xml.Read(),xml.Name) with
    | false,_ -> bookList
    | _, "Author" -> (readAuthor xml)
    | _, "Book" ->  (readBook xml))

  let rec readDoc (xml:XmlTextReader) (bookList:BookXML) =
    seq {
      yield! readDoc xml (parse xml)
    }
It's been a while since I've written F# code to operate on XmlStreams but it's definitely possible and once you get the hang of it, very simple, and you don't have to store the whole tree in memory as you do with the conversion to "objects".


ml like languages are THE perfect languages for working with xml. The algebraic datatypes which you spend the majority of your time creating in them are xml dtd's. The functions you create are xsl transformations. The compiler doesn't allow you to make silly mistakes in any part of your code. See cduce and ocamlduce which are completely based around the idea of xml.

More generally they best suited for "symbolic" programming, compilers being the main example. They don't offer much when you're doing a few things with an api or numeric code (python and numpy are better in that case because of their libraries and because you don't need the additional safety of types when writing small programs/scripts),


The article says

List.map function list - Invokes function on every item within list and returns nothing.

which isn't what map does in other functional programming languages. Applying a function and returning nothing isn't a very functional thing to do in general, as whenever possible functions should be called for their return values, not anything else they might do[0]. Map normally returns a list of the function applied to every element of the list. I looked up the documentation for F#'s map, and it appears to do the same thing:

http://msdn.microsoft.com/en-us/library/ee370378.aspx

[0] And when possible, a function should only return a value, not do other things.


Yes, my mistake sorry. Correcting it now.


Yeah, it's clearly an error on author's side.


I would recommend "Why functional programming matters"[1] paper to anyone struggling to understand the purpose of functional programming. It's only about 20 pages.

[1] http://web.mst.edu/~tauritzd/courses/cs347/whyfp.pdf


That paper is a surefire way to scare people and keep functional programming from those that could use it perfectly well. You, and many others, vastly overestimate how capable even highly educated programmers are in understanding the arguments made in such a technical text.


"Functions are invoked without using brackets or commas"

Is this really a strict property of functional languages? :)


Yeah, the post is mixing essential features of functional languages with incidental points about a specific language's syntax. It's not wrong but somewhat misleading.


I hope it comes across in the preamble that I've been using F# (the only functional programming language I've ever tried out) for just a few days and as such I simply don't know which is which yet.

Anybody who's read this blog post and is interested enough to look further into functional programming should (a) download LINQPad and play around with the interactive F# tutorial and (b) start reading things by people with a few years of functional programming experience under their belt, not a few days.


Fair enough. Sorry if my comment came out as negative, I simply meant to elaborate on bellantoni's comment.

Minor inaccuracies aside, if your post instills the curiosity of a few programmers out there, it's a good thing. Please keep writing. :-)


Not at all, I'm really happy it's garnered so much interest and I'm glad people have taken the time to help correct me / advise what's not quite right.


One thing missed in a big way by this article and other newbies when it comes to (static) functional programming is the centrality of types. It really is what makes ml-derived languages special and it's a shame it's not promoted to non-functional programmers more. Most of your work is related to specifying your types, the rest falls into place naturally, and is why you can think and write code elegantly (and is super fun).


Thanks for the feedback. To be honest I haven't really grasped all the ins and outs of functional programming yet so tried to ignore it as a first step. From what I've seen so far, I do like how much all the typing takes care of itself.


I would really like to hear more about this. I also do type-oriented programming in OO languages, such as Java. The code naturally falls into place, too, but it's just because of Java's verboseness, you end up a lot of hand-waving. But I don't think it differs much from how I would program in functional style, say, in Scala.


This talk by Simon PJ on type classes might be good http://channel9.msdn.com/posts/MDCC-TechTalk-Classes-Jim-but...


I actually have that on a browser tab, and will take a look at it. I know some Haskell (have read maybe 4 books but haven't really ever wrote it).


it all depends on your problem. for gui programming oo code is natural, for transforming complex data structures ml is natural. transforming xml is a horrible mess in java, so xslt is recommended, and xslt is pretty much ml (one of the creators of haskell was a contributor to xslt). it's not matter of java verboseness, even python or lisp isn't well suited to dealing with complex datastructures because they lack the pattern matching over compiler enforced datastructure machinery.


great article...very useful. tyvm!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: