Search code examples
functional-programminglow-level

How is functional programming implemented in low level?


How are Haskell, Scala,... and functional programming languages in general implemented in the low level? That is, how a computer can actually run a functional program if it's Von Neumann? How is the code translated (usually interpreted, I don't know if there are compiled functional languages)?


Solution

  • Short answer:

    By converting the functions to sequences of actions (instructions in some virtual or real machine).

    Longer answer:

    Consider this functional program, using a Lisp notation to free us from syntactical difficulties:

    ;; function definitions
    (defun square (x) (* x x))
    (defun difference (a b)
      (if (> a b)
        (- a b)
        (- b a)))
    ;; actual program
    (difference (square 5) 5)
    

    Assuming strict (not lazy) evaluation, before you can compute the difference, you obviously need to calculate the square. Generalizing on this idea means that in order to compute a function, you first need to compute it's arguments. The order in which the arguments are computed may be unspecified, but for simplicity's sake let's assume that they're computed from left to right. Then, you could transform the above program (omitting function definitions) into the following imperative description:

    1: use value 5 as parameter
    2: call square using 1 parameter, use result as parameter
    3: use value 5 as parameter
    4: call difference using 2 parameters
    

    This sequence of actions can be relatively easily compiled for example for a stack based machine:

    square:
       dup ; duplicate top of stack
       mul ; pops 2 numbers from stack, multiplies them and pushes the result
       ret
    
    difference:
       compare_greater_than ; uses the top 2 numbers from stack, pushes result
       jmpif L ; pops 1 number from stack, jumps if non zero
       swap ; swap top 2 numbers on stack
    L: sub
       ret
    
    main:
       push 5
       call square
       push 5
       call difference
    

    Of course this is only a very rough sketch, but hopefully gives you an idea about where to start. I've implemented a small sketch as well as a more complete version in two of my other answers here. Both are examples of how interpreting a functional program might look like.

    Then, there are also good tutorials on how to actually implement functional languages, like http://www.buildyourownlisp.com/.

    My answer completely focuses on the "practical" approach. There's also a lot of theory which I left out completely, like the spineless tagless G-machine, transformation to continuation passing style or some serious graph stuff, but I hope my answer gives you an idea of where to start.