Lately I've become more and more frustrated that in most modern programming languages I've worked with (C/C++, C#, F#, Ruby, Python, JS and more) there is very little, if any, language support for determining what a subroutine will actually do.

Consider the following simple pseudo-code:

var x = DoSomethingWith(y);

How do I determine what the call to DoSomethingWith(y) will actually do? Will it mutate y, or will it return a copy of y? Does it depend on global or local state, or is it only dependent on y? Will it change the global or local state? How does closure affect the outcome of the call?

In all languages I've encountered, almost none of these questions can be answered by merely looking at the signature of the subroutine, and there is almost never any compile-time or run-time support either. Usually, the only way is to put your trust in the author of the API, and hope that the documentation and/or naming conventions reveal what the subroutine will actually do.

My question is this: Does there exist any languages today that make symbolic distinctions between these types of scenarios, and places compile-time constraints on what code you can actually write?

(There is of course some support for this in most modern languages, such as different levels of scope and closure, the separation between static and instance code, lambda functions, et cetera. But too often these seem to come into conflict with each other. For instance, a lambda function will usually either be purely functional, and simply return a value based on input parameters, or mutate the input parameters in some way. But it is usually possible to access static variables from a lambda function, which in turn can give you access to instance variables, and then it all breaks apart.)

  • 1
    Note that "purely functional" is ambiguous. You probably mean "pure" (free of side effects); "functional" implies a programming paradigm that treats functions as first-class objects and allows for higher-order functions. Those functions do not necessarily have to be pure, and most functional programming languages allow for impure functions.
    – tdammers
    Jun 22, 2012 at 11:20
  • That sounds like an important semantical distinction to make. What I mean with functional is in the mathematical sense, i.e. that the routine only depends on the input data, and neither reads nor writes to any other data in the program. Is "pure function" a more correct term to describe this? Jun 23, 2012 at 19:25

3 Answers 3


Yes, you want to look at Haskell. It does exactly what you want. All functions are pure by default and can only mutate state by using Monads. Also Haskell has very strong static guarantees about all sorts of things http://learnyouahaskell.com/

  • Ah! I've heard a lot of good things about Haskell, but haven't gotten around to looking deeply into it. Maybe it will fit my bill :) Jun 22, 2012 at 11:13
  • It seems to be where a lot of interesting things are going on
    – Zachary K
    Jun 22, 2012 at 11:17
  • 5
    Monads cannot mutate state any more than other data types; they are bound by the same purity constraints as the rest of the language. After all, there is nothing special about them, apart from some syntax sugar. What they can do is provide a convenient abstraction over code that accumulates state through chained or recursive function calls, and when compiled against the runtime, such code boils down to imperative code similar to what the monadic code looks like. It's still an abstraction though, and the code is still 100% pure.
    – tdammers
    Jun 22, 2012 at 11:18
  • 4
    Also, functions aren't pure by default, they are pure, period. Haskell cannot express impure functions.
    – tdammers
    Jun 22, 2012 at 11:21
  • 3
    @CPX: There are at least three industry-strength web frameworks for Haskell (Yesod, Happstack, and Snap), and an abundance of libraries for practically all the tasks you mention (not sure about SOAP though); the average code quality within the Haskell ecosystem tends to be excellent. The biggest problem I can forsee is finding enough programmers to support such a thing over a longer maintenance period.
    – tdammers
    Jun 22, 2012 at 12:39

C and C++ have very limited support for at least part of the problem through the const keyword; while this alone does not control purity, it can be used (especially in C++) to tell the compiler that a particular data structure is not to be modified through a given pointer. Some compilers (e.g. gcc) also provide a 'pure' attribute as a language extension to fully enforce purity. (See this question for details).

The D programming language has support for declaring the purity of functions explicitly, and compilers will check and enforce purity (that is, trying to call a non-pure function from within a pure function yields a compiler error).

Haskell is completely pure, that is, the language itself cannot express impure functions, and there is no concept of a 'routine'. Anything that cannot be solved using pure functions alone is outsourced to the (impure) runtime; a program with side effects is implemented by building (using exclusively pure constructs) a lazy data structure that describes the program behavior, and then handing it to the runtime. The Haskell community is actively experimenting with a whole zoo of programming languages, some of them pure, others with explicit purity.

There may be more, but these are the ones I'm familiar with.

  • gcc does support explicit declarations of purity as an extension like so
    – Useless
    Jun 22, 2012 at 12:23
  • C++'s const member functions do control purity, if your classes have no non-const member functions. All data becomes constant, and then everything is pure functional.
    – tp1
    Jun 22, 2012 at 18:27
  • @tp1: Not quite. A const member function can easily produce side effects by calling non-const static methods of other classes, instantiating other classes, or simply calling free functions or modifying global variables. It only works if you lock down your entire codebase to all-const, including all the libraries you use (even STL).
    – tdammers
    Jun 22, 2012 at 19:30
  • @tdammers: The all-const lock down is not very bad since the data can be initialized to different values by constructor parameters. But it does require all your data be located inside your classes and not in global variables.
    – tp1
    Jun 22, 2012 at 19:36
  • @tp1: It's also very impractical, because it reduces the number of libraries you can safely use to practically zero.
    – tdammers
    Jun 22, 2012 at 19:42

Felix has three categories it seems:

  1. functions

    There is a rule for functions: 
    A function introduced by a fun binder is not allowed to have any side effects.
    The compiler does not enforce this rule, but it does take advantage of it when
    optimising your code. 
  2. procedures

    Procedures do not return a value, and may and generally should have side-effects.
  3. generators

    A generator is a function that may have side effects.
  • This sounds like a language that tries to do precisely what I am after. It's unfortunate that functions aren't compiler-enforced, though (after a few years working professionally I have developed a knee-jerk mistrust for other programmers' libraries ;-)). Also, since it's so new, I might tinker with it, but it doesn't sound like a candidate for commercial/professional development :( Jun 23, 2012 at 19:29
  • 1
    @ChristianPalmstierna: Just stumbled across this years old question. Unfortunately, like so many interesting properties, deciding whether a function is pure, is equivalent to solving the Halting Problem. Note that this doesn't necessarily mean that you can't do it, it just means that there are infinitely many pure functions whose purity the compiler cannot prove and thus must reject as impure even though they aren't. (This is no different from static typechecking, though. Typically, there are infinitely many programs which are safe but cannot be proven type-safe. Doesn't stop us from typing.) Jan 15, 2015 at 4:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.