I just finished writing a series of posts, Twelve Monads of Christmas, on medium.com. If you like Haskell you might like it; otherwise it will be incomprehensible.
20 December, 2016
In 1998, I was given a fibre optic christmas tree, lit by two coloured light bulbs powered by 2 x AA batteries. In the intervening years, the electrics broke. Finally today I got round to doing something about it.
Unfortunately, I can't see much of a different between the illumination provided by the seven pixels - I was hoping that each one would light the fibres up very differently, but that hasn't turned out to be the case. No big deal though, and maybe more optical isolation between the different LEDs and the base of the fibre bundle would help.
Interestingly, the fibres manage to project an image of the layout of the LEDs on the board (see link above) onto the wall behind the tree! and all the fibres emit a very slight blue light because there's a blue LED on the controller board.
25 November, 2016
The Haskell unit type,
(), has just one value, also written
smuggle :: Typeable t => t -> () discover :: Typeable t => () -> Maybe t x :: () x = smuggle "hello world" discover x :: Just String Just "hello world"
These allow you to inject an arbitrary (Typeable) Haskell value into unit and retrieve it later. Just don't try to inspect the resulting
Rather than Haskell 98, you'll need unsafePerformIO and extensible exceptions, put together in a way that lets you hide arbitrary stuff in a thunk, and force evaluation at just the right time.
smuggle :: Typeable t => t -> () smuggle v = unsafePerformIO $ throw (toDyn v) discover :: Typeable t => () -> Maybe t discover v = either (fromDynamic) (const Nothing) $ unsafePerformIO $ try $ case v of () -> return ()
I could write more. But it's Friday night and I want to drink my wine.
Edit: This is now available on hackage as acme-smuggler.
24 November, 2016
When you're in a cafe
64 bytes from 220.127.116.11: icmp_seq=3 ttl=59 time=26.8 ms 64 bytes from 18.104.22.168: icmp_seq=4 ttl=59 time=23.9 ms 64 bytes from 22.214.171.124: icmp_seq=5 ttl=59 time=26.0 ms
and then their internet dies
From 192.168.1.254 icmp_seq=28 Destination Host Unreachable From 192.168.1.254 icmp_seq=29 Destination Host Unreachable From 192.168.1.254 icmp_seq=30 Destination Host Unreachable
and then there is a power cut
From 169.254.6.166 icmp_seq=51 Destination Host Unreachable From 169.254.6.166 icmp_seq=52 Destination Host Unreachable From 169.254.6.166 icmp_seq=53 Destination Host Unreachable
but that reset the router
64 bytes from 126.96.36.199: icmp_seq=1786 ttl=59 time=20.7 ms 64 bytes from 188.8.131.52: icmp_seq=1787 ttl=59 time=24.0 ms 64 bytes from 184.108.40.206: icmp_seq=1788 ttl=59 time=21.5 ms
and all is good in the world again.
10 November, 2016
01 August, 2016
09 March, 2016
I got a NooElec R820T Software Defined Radio.
Only got a kernel stack trace once, trying to unload the automatically loaded digital TV drivers. And I didn't have to compile anything.
About half an hour after unboxing, I was using gqrx to get a waterfall plot of various things - BBC Radio 1, Capital, PMR446, the London bus trunked radio system, GB3LW, some local business users, and some (not-decoded) ADS-B plane traffic and some classical music being played in the CB range.
I think it needs a better antenna though - I can pick up stuff ok on my Baofeng handheld that I'm not getting through this.Also might be interesting to see if a Raspberry Pi 2 is powerful enough to run this.
02 March, 2016
The Adafruit tutorial for flashing an LED using Lua on an ESP8266 is buggy: The main loop does not yield to the underlying operating system, and instead hogs the CPU causing eventual crash - usually after about 10 seconds for me.
Here's the code reproduced from the tutorial:
while 1 do gpio.write(3, gpio.HIGH) tmr.delay(1000000) -- waits a second, without allowing OS to run gpio.write(3, gpio.LOW) tmr.delay(1000000) -- and again end
The NodeMCU people advocate using a node.js async callback style, where instead of delaying your thread, you would instead set an alarm for a callback to do the next thing. Using
tmr.delay and looping a lot is strongly discouraged because it upsets the OS.
I hate that callback style of coding (for reasons).
Lua has co-routines, though, apparently because people wanted to do things like write scripts that kept yielding back to a game engine and then resuming. (See this history of Lua)
I've recently been playing with effect systems in Haskell (see blog tag extensible-effects) and realised that Lua co-routines provide enough infrastructure for (some of) this.
So I hacked up a prototype.
The "user program" looks very much like the Adafruit example:
flashDelay = 200 -- ms function flasher() while 1 do gpio.write(3, gpio.HIGH) coroutine.yield(flashDelay) gpio.write(3, gpio.LOW) coroutine.yield(flashDelay) end endand can be run like this;
You can also use
driveCoroutineBad which uses the blocking
tmr.delay instead of the asynchronous
tmr.alarm, and get the same ESP-crashing behaviour as the original example.
The main difference is that calls to
tmr.delay are replaced by a call to
yield. In effect system language, that means the code is asking the effect handler (
driveCoroutineBad) to perform an effect (to delay by the appropriate time) rather than performing the effect itself. How that actually happens is down to the effect handler: in the bad case, just calls
tmr.delay; and in the good case, does all the wrapping up of callbacks for
This ends up looking almost identical to the code in this GitHub issue, tmr.delay() is synchronous and blocks the network stack.
On a very simple example, this is a bit overkill, but on a bigger example is probably more interesting: you can call
coroutine.yield deep down inside a whole stack of functions, which becomes tangly if you're trying to build this manually as an async callback.
Other callback style stuff is hopefully amenable to this - for example, socket handling.
25 February, 2016
19 February, 2016
I got a Pebble Time smartwatch, but it turns out I don't wear it much, despite wearing my original (OG) Pebble all the time. I don't even keep it habitually charged.
There isn't one particular reason:
- There are two reasons why I have to keep taking the watch off, something I never had to do with the OG Pebble which I wore 24/7:
- The charge port is inaccessible while wearing the watch. I didn't realise before hand how much of a problem that would be: I tend to take it off to charge and forget to put it back on.
- The wristband and/or shape does something weird to my skin that neither the OG pebble nor the 10 wristbands I wear do; especially if the Pebble gets wet (which it otherwise would often, several times a day).
- Application loading is heavily coupled to the phone. I got the Pebble because it has long battery life, but I've found myself in situations where I can't use (e.g.) the compass because my phone has gone flat (which is does by the end of every day). That turns the compass from something I can rely on into a gimmick.
- Not really an ongoing reason, but as I'm in grumble mood, I found the software upgrade experience from OG to Time quite frustrating: I needed a different app from the Pebble app that I already had installed, and it seemed to conflict in a weird way with the existing app.
I have been hoping someone would make a smartstrap to expose charging, but to no avail. Now there's an SDK available for the serial port (which is also the charge point), I might start fixing that problem myself. One day.