StandardML - gregorymorrison/euler1 GitHub Wiki

Standard ML, introduced in the late '70s, is a functional language whose niche seems to be solely in academia. I knew nothing of it previously, and imagine that none of my coworkers do, either. My impression so far is that it has much of the same feel of languages like OCaml and Haskell, though I struggled with it more. I had a much harder time finding documentation and struggling with the strict type system. For example, it took me probably five hours to figure out how to output an integer returned from a function to the screen - I couldn't figure out how to make the type system happy. Overall, this version of Euler1 took me approximately a whole day. This surprised me, since this this should have been a simple translation of my OCaml version.

I was also surprised that writing recursive code was nontrivial in this language. My perception is that Standard ML should be smart enough to generate efficient recursive code using tail call recursion, etc. But my first efforts generated horrible code that took minutes to calculate Fibonacci(100), and Fibonacci(1000)  actually overflowed the stack. It took me an hour to figure out how to write a recursive version that actually ran, though when I did, it ran efficiently. Expect a significant learning curve. Here is my version of Euler1, including the aforementioned troublesome print line:

(* Euler1 in Standard ML *) 

local
    fun f 1 acc = acc
      | f i acc = f (i-1) (if i mod 3 = 0 orelse i mod 5 = 0
                            then acc + i
                            else acc)
in
    fun euler1 size = f size 0
end; 

print (Int.toString( euler1 999 ) ^ "\n");

I used the open-source Mlton compiler. This compiler is extremely slow, taking at least a minute to compile the above on my Netbook. This caused even more frustration, as I had to wait that much longer to get the obscure error messages complaining about type errors. The generated code seems to be fast enough, though. Simply call the compiler, passing it your program as an argument, then execute the generated object file.

$ mlton euler1.sml
$ ./euler1
233168
$