It's salt

... because it's about time I got a "blog."

HTTP or WWW

I don’t see why the Chromium developers decided remove the “http://” in the URL bar in favor of a globe icon. Clearly something in the URL should be replaced with an image, since images are what people get. But why the “http://”?

What should have been replaced with the globe icon is the WWW in URLs. Since WWW, last I checked back in 1996, stood for World Wide Web, this would make total sense. Not only that, it also avoids all those copy and paste bugs people are complaining about.

I think the Chromium developers made a huge mistake.

Did you know?

Backmasking on the Liars track We Live NE of Compton

My MacBook Pro Has Outputs I Didn’t Know About

Something I didn’t know until a few days ago: MacBook Pros come with combo audio jacks. That’s right, both input and output jacks can take an 1/8” electrical or S/PDIF plug. You’re probably thinking …great. I assure you, this a good thing to know in case you’re ever in the situation I was in a couple days ago.

I was listening to music on my headphones, when for some reason I decided to unplug them and use my MacBook Pro’s internal speakers. Instead of aural stimulation, I was greeted with silence. I was trying unsuccessfully to turn the volume up when I noticed the mute icon in the on-screen volume display, even though the volume was maxed.

Properly confused, I tried plugging in my headphones again, removing them, plugging them in again, ad nauseam. Finally I noticed a light of sanguine hue falling on my finger as I removed my headphones from the audio jack. My first thought was that my audio jack was broken, and this light was some sort of problem indicator. I went to google for confirmation, where I learned that in a way it was, but it really wasn’t.

What I was seeing was an enabled S/PDIF output, enabled somehow by a switch (electrical, mechanical, or otherwise) inside the jack. Some people reported having to bring MacBooks with similar symptoms in for repair. Others suggested a fix involving shoving a toothpick into the jack to set the switch causing the malfunction to the proper state. Since I wasn’t comfortable with either of these solutions, I plugged in my headphones once more, wiggled the jack around something fierce until, eventually, something in there went right and I had the use of my internal speakers back.

So who knew? You get a two-for-one deal on audio jacks when you buy a MacBook Pro. I’m glad I paid for features I’ll never use and, if it wasn’t for a hardware malfunction, would never have been aware of!

Mike: Gorilla by me

Mike: Gorilla by me

Brian the Monkey by me

Brian the Monkey by me

Faces by me.

Faces by me.

Dead Christ tended by Angels by Donatello

Dead Christ tended by Angels by Donatello

Who’s Afraid of the Big Ol’ unsafePerformIO?

A couple of months ago while in New York I got a call from a friend in need of some Haskell help. He was working on a project for a Comp. Bio course and he needed to implement the Knuth Shuffle, but he was having a bit of touble using Haskell arrays. His problem involved some type error that I couldn’t tackle over the phone, so it had to wait until later.

Once I got home, I got onto Wikipedia and looked up Knuth Shuffle. Seeing it was an inherently imperative algorithm, I wasn’t totally surprised my friend hit a few bumps while trying to translate it to Haskell. I decided to go ahead and implement my own version so I’d have a better understanding of what he was doing. I called him later that night to help him fix the problem, but by that time he had figured it out.

The implementation I wrote sat around on my hard drive untouched for a couple months until I rediscovered it last week. For your viewing pleasure, here it is:

module Permutation ( permute ) where

import Data.Array.MArray
import Data.Array.IO

import System.Random


permute :: [a] -> IO [a]
permute xs =
  let len = length xs in
    do a <- newListArray (0, len - 1) xs
       mapM_ (\i -> randomRIO (i, len - 1) >>= swap a i) [0..len-1]
       getElems a

swap :: (Ix i) => IOArray i a -> i -> i -> IO ()
swap a i j = do e1 <- readArray a j
                e2 <- readArray a i
                writeArray a i e1
                writeArray a j e2

Looking this code over, a question came to mind: can I pull the permute function out of the IO monad by using unsafePerformIO? The documentation page for unsafePerformIO lays down some cursory guidelines for its use:

This is the “back door” into the IO monad, allowing IO computation to be performed at any time. For this to be safe, the IO computation should be free of side effects and independent of its environment.

If the I/O computation wrapped in unsafePerformIO performs side effects, then the relative order in which those side effects take place (relative to the main I/O trunk, or other calls to unsafePerformIO) is indeterminate.

The second part of this disclaimer points out the essential problem with allowing mutation in a lazy language: without any guarantee of when an expression will be evaluated, one does not know when or in what order side effects will take place. Hence the IO monad, which requires the programmer sequence computations that may produce side effects or may depend on some mutable state.

But what if you don’t care when a side effect takes place? What if you don’t care when a computation is performed relative to other side effects? unsafePerformIO in essence allows you to say exactly that about a computation; it removes that computation from the IO monad, thus absolving the programmer of the task of specifying when, relative to other computations, the computation should be performed. However the documentation for this function tells us it is only “safe” if, i.e., it is necessary that, “the IO computation … be free of side effects and independent of its environment”. This certainly seems like a sufficient condition; if I can say that about a computation, then it certainly doesn’t matter when or in what relative order the computation is performed. Is it necessary? No, and I belive the permute function above proves it.

permute does mutate global state: the state of Haskell’s random number generator (stored in theStdGen) is modified by each call to randomRIO. It is dependent on its environment: the value in theStdGen determines the values produced each time randomRIO is called. Despite this it would be absurd to claim the state of Haskell’s random number generator matters to me each time I want to permute a list, or that it matters when I modify the state of the random number generator relative to other computations. Therefore, I can define permute as follows:

permute :: [a] -> [a]
permute l = unsafePerformIO $
  let len = length l in
    do a <- newListArray (0, len - 1) l
       mapM_ (\i -> randomRIO (i, len - 1) >>= swap a i) [0..len-1]
       getElems a

A few more issues need to be addressed. The documentation page for unsafePerformIO mentions three precautions one must take when compiling a module using this function. All of them address unintended behavior that arises due to optimizations performed by GHC (under the assumption of referential transparency).The NOINLINE pragma is essential. It doesn’t seem as though common subexpression elimination or let-lifting will be an issue in the module. However, uses of permute could fall victim to either of these optimizations. As an example, consider the following expression:

[permute [1..4], permute [1..4]]

If this expression is in some compiled module, GHC could potentially (almost certainly) identify the common subexpressions and transform the expression it into the following:

let e = permute [1..4] in [e, e]

Obviously, this wouldn’t be a good thing, since instead of getting two (likely) distinct permutations, one would always get the same permutation. To avoid this, use the -fno-cse option when compiling such a module.

The exception

A possible objection one might raise to all of this is that it is possible to set the state of Haskell’s random number generator by using the function setStdGen. After the state of the generator is set, the generator ceases to be “random” and becomes observably deterministic and so it would matter when this action is performed relative to calls to permute. Such an objection I belive is right, or at least tenable. So don’t do it!