-
-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Contracts? #157
Comments
Thank you for opening this issue, @jackfirth, and for going into quite a bit of detail! Apologies in advance for going off on a slight tangent. :) Let's consider a familiar function, map :: Functor f => (a -> b) -> f a -> f b With sanctuary-def, the closest we can currently get is (String -> Integer) -> Array String -> Array Integer Now, sanctuary-def gets us closer: [$.Function, $.Array($.String), $.Array($.Integer)] What if we could write function(x) {
if (/* `x :: String` not satisfied */) {
throw new TypeError('…');
}
var result = f(x);
if (/* `result :: Integer` not satisfied */) {
throw new TypeError('…');
}
return result;
} This is achievable. Dealing with type variables is more involved. Let's take another step: [$.Function([a, b]), $.Array(a), $.Array(b)] We'd first determine the set of types common to the
This is achievable, though not straightforward. The final step is to support "higher" type variables such as the I'll spend some time playing with sweet.js to see whether it supports bounded parametric polymorphism. If it does, I'll study the code it generates to do so. I'd love to add this functionality to sanctuary-def. Another option is to use sweet.js itself, of course, though I'm keen to avoid a build step if possible. |
Contracts.js includes support for enforced parametric polymorphism out of the box. This is implemented via opaque wrappers and a notion of blame. For example in the case of filtering an array, which has type When filtering for odd numbers, If you're looking to adding this behavior to
I am not sure how to extend contracts to higher kinded types like Functors. Asking the Racket mailing list / users group about this would be a very good idea. |
This is fascinating, @jackfirth. I will make time to read and watch these various resources. |
Closing in favour of sanctuary-js/sanctuary-def#63. |
Sanctuary strives to complement Ramda with safe, total functions providing strong guarantees about their behavior. Enforcement is via first-order type checking, e.g. throwing TypeError when given a Number where a String is expected. However, higher-order properties are more difficult to enforce - how does one verify that the function given to
Maybe.filter
returns a boolean? You can check that the given value is a function but that's not enough, you'd have to check that it returns a boolean every time it's called in the implementation ofMaybe.filter
.Contracts are designed to solve this problem:
And just look at the error messages!
That funny looking
@ ...
line, as careful readers might note, isn't valid javascript. It's asweet.js
macro, a rule for transforming code from arbitrary syntax into valid javascript. The Sweet JS macro and build system provides a framework for defining these macros, and tools to generate "normal" javascript from "sweet" javascript. Using these contracts in Sanctuary would therefore imply some nontrivial wrangling of its current build system and release process, but it would be invisible to clients of the library. I would argue it falls well within the philosophy of Sanctuary to provide this.The text was updated successfully, but these errors were encountered: