I was just considering a nicer interface for computeHmac at a library level, but if you don't have that, you could still just implement checkHmac using your Secret class and call it with checkHmac(Secret(str), message, mac).
It's turtles all the way down. Without the secrets monad support in the language, at some point I have to be the one enforcing secrets in multiple places: if I implement checkHmac(secret(str),...) that calls computeHmac(str)->str then I must both "unbox" the secret(str) _and_ "box" the return value of computeHmac.
I can do this, sure, and if I forget then I'll have a security bug. This is similar to the situation with c++ destructors over c's manual malloc+free. If you're happy freeing at every function's end, then this secrets thing adds nothing for you, and that's cool. It's your own choice what language to use.
If you try to call computeHmac from checkHmac surely you'll get some sort of error or warning, wouldn't you? You have no guarantee computeHmac will your secret will be treated as a secret by computeHmac, if its signature is simply "str". Unboxing it is never safe.