Implementing Probabilistic Modeling Using Monads in F# and Scala

For my induction into Scala, I wanted to translate the probabilistic monad of Chapter 9 of Expert F# (Introducing Language-Oriented Programming). The idea, based on the paper Stochastic Lambda Calculus and Monads of Probability Distributions, is to define a probability monad to compute over distributions of a domain instead of the domain itself. We limit ourselves to distributions over discrete domains characterized by three functions:

  1. sampling

  2. support
    (i.e. a set of values where all elements outside the set have zero chance of being sampled)

  3. expectation of a function over the distribution
    (e.g. the probability of selecting element A by evaluating the function f(x) = 1 if x equals A and 0 otherwise)


Contrast the F# implementation with the Scala implementation. The Scala implementation closely follows the F# one, except for one major frustration: the type inference is not as powerful in Scala, as all function arguments must be declared.

Perhaps, I am missing a few tricks because I am new to Scala. If anyone has any suggestions for improving the Scala implementation, please share.

Cross-posted to the Scala wiki.

the killer combination for programming languages or why I like F#

I've been using F# to develop a plug-in to AutoCAD for designing microfluidic chips (user site, developer site). I came to F# because my project required an implementation in a .NET language, and I felt that a functional language would be a good match for my problem domain. Now, it's my language of choice, and I feel guilty for tying myself to a closed platform. What do I like about F#?

Type inference, static typing & visual type feedback. The code is more concise, because type declarations can be omitted. This conciseness also makes it easier to modify the code, and static typing ensures that modifications are safe. This comes at no loss in clarity, because Visual Studio supplies the inferred type on demand. In addition, Visual Studio continuously informs of type errors, which allows an instantaneous overview of the consequences of a modification. Code can easily be drastically modified, even if maintainability was not consciously thought of during the development process. Haskell and OCaml also have this combination of type inference and static typing, but without the instantenous type feedback leveraged by the Visual Studio integration.

Language-oriented programming. In F# like "in Lisp, you don't just write your program down toward the language, you also build the language up toward your program" (Paul Graham in Programming Bottom-Up). In F#, like in Haskell and OCaml, you build an abstract representation of your domain using algebraic data types and analyze it with pattern matching. Functional programming with higher-order abstractions also help in this regard (not to mention that it's fun).

Python-like syntax. With the #light option, F# becomes indentation-sensitive, allowing for more conciseness and readability. Haskell has a similar option.

F# Interactive. It's nice to have a REPL sometimes.

.NET and Visual Studio integration. Unlike its cousins, F# is eminently practical just by virtue of being a .NET language. You can easily mix and match components written for the CLR. In addition to the type feedback, Visual Studio has a great debugger. I also like the C#-like classic object-oriented system, though probably because it's familiar rather than superior.

In conclusion, programming in F# feels fun & productive and (yet) professional & practical. I used to be content programming an esoteric Scheme system in Emacs. Now, I am convinced by the killer combination of (1) a fun functional language (2) a widely-used platform with a rich library (3) an IDE with a good visual debugger. With (1) ML-like, (2) CLR, (3) Visual Studio, you get F#. With (1) Lisp, (2) JVM, (3) Eclipse, I guess you get Clojure. That's the future.

Labels