This is one great question I've wrestled with over the years.
Right now, all three programs would result in a different hash. I decided that the scrapyard publication process should do as little "magic" as possible.
As the tooling evolves, we can provide a canonicalizer scrap that renames variables and simplifies the code. I think eventually we would make this the default process to encourage more reuse.
You might want to look into the way Unison does things: [1], they've got a lot of similar ideas and IIRC the way their hash system works avoids that ambiguity.
I didn't read it in-depth yet, but I think I had a previous implementation that worked very similarly to theirs.
The problem with variable names is that they actually matter for some of the collaborative editor features I hope to implement in the future. There are certain assumptions I can't make quite yet, and so am keeping my options open :)
Have you thought about using type aliases or higher order types of some sort for that instead of relying on the variable name?
I could define that a familyname and a givenname are strings, and then a function argument of type familyname would be differentiated from a function argument of type givenname, but still the argument names themselves could be dropped from the hash.
Right now, all three programs would result in a different hash. I decided that the scrapyard publication process should do as little "magic" as possible.
As the tooling evolves, we can provide a canonicalizer scrap that renames variables and simplifies the code. I think eventually we would make this the default process to encourage more reuse.