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
andtoCommandData
to reify theGivenCmd
andCmdData
into the "flat" ADT to be passed to theCommand
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?