A “Monte Hall” problem solved in Haskell

I’ve just written a solution to today’s Programming Praxis puzzle, which requires you, essentially, to write a Monte Carlo attack on the Monty Hall problem. Thus, the awful pun in this post’s title, in case you missed it. ;-)

Here’s my solution.

It was a lot of fun. I started out feeling like I should be able to do it, but not quite knowing what direction to take, so first of all I was writing some data types for things like Door = Car | Goat, etc. but pretty quickly realised it was just a matter of door numbers. My first working solution was actually a bit longer, because of some intermediate steps (for example the first thing I figured out, in its own function, was how to compute which goat door would get shown to the player given a (car, choice) pair). Then hlint gave me a couple of hints, like using replicateM, and I compacted it down to what we see here. I’m sure it has naive aspects, but I’m pretty happy with it — and I’m loving doing the Praxis problems.

2 Responses to “A “Monte Hall” problem solved in Haskell”

  1. July 25th, 2009 | 3:21 am

    Haha! I used replicateM and “filter id” followed by “length” today too, but in the list monad, not IO. Was using it to help compute some dice probabilities. I ended up using a spreadsheet (which SPJ commented is “the world’s most popular functional programming language”, though it’s “zeroth order”, i.e. doesn’t have functions).

    It occurs to me that “length . filter id” could also be expressed as “sum . map fromEnum” since fromEnum False = 0 and fromEnum True = 1. If you want to think like a C programmer for a while :)

    I don’t think there’s a “nicer way” of picking a random number, if by that you mean “not in IO”, unless you’re content to pick a seed and use a pseudorandom source, since randomness is obviously not referentially transparent and so can’t be allowed in pure code. ISTR there being a randomness monad on Hackage, but I don’t think that would help here. If you mean “using one function instead of two”, look no further than randomRIO.

  2. July 25th, 2009 | 8:27 am

    No, I’m happy with being in IO for PRNG. I didn’t mean so much a nicer way of picking a random number (I got that straight from the System.Random documentation), but rather, of making a random choice from a list. My chooseFrom is inspired directly by python’s random.choice(). On that note, I thought the python solution presented before mine on the Praxis page was impressively short – but semantically weird. For each of n trials it calls trial() /twice/ in order to work out whether switching was a good strategy (and since the randomisation happens in trial(), it’s not even calling it twice for the same problem instance!).

    I haven’t got my head round the list monad yet… :-)