Skip to content

Instantly share code, notes, and snippets.

@adinapoli
Created July 31, 2015 07:22
Show Gist options
  • Save adinapoli/1fe291c72b4bb89c76a5 to your computer and use it in GitHub Desktop.
Save adinapoli/1fe291c72b4bb89c76a5 to your computer and use it in GitHub Desktop.

I'm building an Haskell implementation of the Myo armband WebSockets specification:

https://developer.thalmic.com/forums/topic/534/

The API per se it's quite run-of-the-mill, but with a twist. You can send "command" to the Armband, but the json payload describing them it's quite indulgent. As an example, these are 2 possible commands:

{"command": "set_stream_emg",
 "myo": <number>, // Myo ID (unsigned integer)
 "type": "enabled" | "disabled"
}

{"command": "vibrate",
 "myo": <number>, // Myo ID (unsigned integer)
 "type": "short" | "medium" | "long" // Vibration type
}

Here "type" can potentially be any type of the enumeration of all the possible command types. Which means the user can build something with no semantic sense like

{"command": "set_stream_emg",
 "myo": <number>,
 "type": "short"
}

To make this type safe I reached for type families, as it can be seen here:

https://github.com/adinapoli/myo/blob/master/src/Myo/WebSockets/Types.hs#L188

This works and the API is not too bad. This will typecheck:

newCommand myoId Vibrate Long

but this won't:

newCommand myoId Vibrate Enabled

What I do not like:

  • Those two functions toCommandType and toCommandData to reify the GivenCmd and CmdData into the "flat" ADT to be passed to the Command record
  • It seems there is lots of indirection, but it stems not only from the usual kind-promotion boilerplate when doing type-level programming, but also from the fact that, ultimately, I still need plain & simple types for Command or it won't typecheck.

Can I do any better? Can the singleton library help me here to scrap a bit of boilerplate?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment