Skip to content
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

[email protected] #232

Merged
merged 1 commit into from
Jan 12, 2017
Merged

[email protected] #232

merged 1 commit into from
Jan 12, 2017

Conversation

davidchambers
Copy link
Member

@davidchambers davidchambers commented Jun 13, 2016

This pull request:

  • makes the Either and Maybe types compatible with Fantasy Land v2.2.x;
  • removes type checking from Either and Maybe methods;
  • removes the Ramda dependency;
  • defines S.__;
  • adds sanctuary-type-classes as a dependency; and
  • updates the sanctuary-def dependency to v0.8.0 (as described below).

Original description:

This pull request is not yet ready to merge since [email protected] is not yet available, but I couldn't wait any longer to share this. We now have the ability to describe higher-order functions via sanctuary-def!

S.find(x => x, ['foo', 'bar', 'baz']);
// ! TypeError: Invalid value
//
//   find :: (a -> Boolean) -> Array a -> Maybe a
//                 ^^^^^^^
//                    1
//
//   1)  "foo" :: String
//
//   The value at position 1 is not a member of ‘Boolean’.

HOLY SMOKES, BATMAN!

Consider the updated type of find:

-[$.Function, $.Array(a), $Maybe(a)]
+[Fn(a, $.Boolean), $.Array(a), $Maybe(a)]

What we currently know as $.Function is to be renamed $.AnyFunction. $.Function will be a type constructor of type Array Type -> Type$.Function([$.String, $.Integer]), for example, will represent String -> Integer. Since curried functions are so common in the Sanctuary codebase I defined Fn :: (Type, Type) -> Type so we can write Fn(a, Fn(b, c)) rather than the noisy $.Function([a, $.Function([b, c])]).

@Avaq, you'll be able to update #191 once this pull request has been merged. :)

The one other sanctuary-def feature I would like to add before publishing the next version is support for parameterized type variables. That will mean we can accurately describe the type of a function such as lift :: Functor f => (a -> b) -> f a -> f b!

@davidchambers
Copy link
Member Author

I added $.UnaryTypeVariable to sanctuary-def, so the type of lift is now [Fn(a, b), f(a), f(b)] with the constraint {f: [Functor]}. 🎉

@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 2 times, most recently from acfe6fa to 9c421cc Compare July 5, 2016 04:53
@davidchambers davidchambers mentioned this pull request Sep 14, 2016
33 tasks
@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 2 times, most recently from 4e22761 to 89f3a75 Compare September 28, 2016 11:42
@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 4 times, most recently from 5790ed7 to a367dd0 Compare October 2, 2016 13:50
@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 2 times, most recently from 6d72f19 to 472eecd Compare October 11, 2016 17:34
@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 2 times, most recently from 4567a75 to fd83fe1 Compare October 16, 2016 11:21
@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 4 times, most recently from 1301d5b to 4f849d6 Compare November 4, 2016 14:36
@@ -11,6 +11,7 @@ describe('on', function() {
it('is a quaternary function', function() {
eq(typeof S.on, 'function');
eq(S.on.length, 4);
eq(S.on.toString(), 'on :: (b -> b -> c) -> (a -> b) -> a -> a -> c');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's exciting to be able to express the types of functions such as this one, @Bradcomp. :)

var dependencies = ['sanctuary-type-classes', 'sanctuary-def'];

eq(dependencies.slice().sort(),
Object.keys(require('./package.json').dependencies).sort());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shard, this is my low-tech fix for #309. How does it look to you?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea this is probably the better way now that I think about it, just having a test check if things are out of sync.

👍

//. makes it possible to write safe code without null checks.
//. Sanctuary is a functional programming library inspired by Haskell
//. and PureScript. It's stricter and more opinionated than [Ramda][].
//. Sanctuary makes it possible to write safe code without null checks.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jacse, let's collaborate. I like your changes in #317, but since this pull request removes our Ramda dependency we must update the introduction accordingly. Feel free to suggest changes and/or additions to the paragraph above. :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidchambers looks good, but maybe we should mention that Sanctuary can/should be used as an alternative to Ramda. On the top of my head: "It includes much the same functionality as Ramda, but is stricter and more opinionated."

I think this would make it more clear what functionality people can expect from Sanctuary ("write safe code without null checks" can be a bit vague). Most likely developers diving into functional programming in javascript will take a look at both Ramda and Sanctuary and I think a wording along these lines would make the relationship between them clear.

Just my 2 cents.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it. I'll make the change you have proposed.

When Sanctuary first came into existence it was focused on avoiding the null checks which several Ramda functions require. Sanctuary's scope is now much broader.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the introduction. I went with "provides a similar suite of functions" rather than "includes much the same functionality".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidchambers yeah that's better.

test('"sequence" method', function() {
eq(S.Left('abc').sequence.length, 1);
eq(S.Left('abc').sequence(S.Maybe.of), S.Just(S.Left('abc')));
test('"fantasy-land/reduce" method', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to sequence?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #257 for the discussion which led to its removal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I missed that one.

'1) null :: Null\n' +
'\n' +
'The value at position 1 is not a member of ‘Function’.\n');
test('"fantasy-land/extend" method', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about filter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was also discussed in #257.

'1) null :: Null\n' +
'\n' +
'The value at position 1 is not a member of ‘List a’.\n');
eq(S.indexOf.toString(), 'indexOf :: a -> List a -> Maybe Integer');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused as to what the criteria are for using Array over List in various type signatures. indexOf seems to me to be more an array function than a list one given how expensive it is for the latter data structure.

Copy link
Member

@Avaq Avaq Jan 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the List type in Sanctuary is just a union of Array, String and other types with a length, excluding functions. The type signature has Array when the function would not work on all of these other types as well; https://sanctuary.js.org/#list

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The List type attempts to unify $.Array and $.String. It doesn't have anything to do with linked lists. It's a confusing type, certainly!

List

The List type constructor enables type signatures to describe ad hoc polymorphic functions which operate on either Array or String values.

Mental gymnastics are required to treat arrays and strings similarly. [1, 2, 3] is a list containing 1, 2, and 3. 'abc' is a list containing 'a', 'b', and 'c'. But what is the type of 'a'? String, since JavaScript has no Char type! Thus:

'abc' :: String, List String, List (List String), ...

Every member of String is also a member of List String! This affects the interpretation of type signatures. Consider the type of indexOf:

a -> List a -> Maybe Integer

Assume the second argument is 'hello' :: List String. a must then be replaced with String:

String -> List String -> Maybe Integer

Since List String and String are interchangeable, the former can be replaced with the latter:

String -> String -> Maybe Integer

It's then apparent that the first argument needn't be a single-character string; the correspondence between arrays and strings does not hold.

As for S.indexOf and S.lastIndexOf, I'd really like to remove these functions. Addressing array elements by index is not a practice we should encourage.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressing array elements by index is not a practice we should encourage

🏅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, I vaguely remember the discussions we had about List a few months ago now.

@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 11 times, most recently from 1c4a09d to 5b277bf Compare January 12, 2017 04:52
@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 4 times, most recently from 4c96b25 to 76aaed2 Compare January 12, 2017 05:44
// negativeZero :: a -> Boolean
var negativeZero = R.either(R.equals(-0), R.equals(new Number(-0)));
// Thunk :: Type -> Type
function Thunk(x) { return $.Function([x]); }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@safareli, we can replace $.Function([x]) with $.Thunk(x) once sanctuary-def supports this. :)

@davidchambers davidchambers force-pushed the dc-sanctuary-def branch 2 times, most recently from 726a105 to 5d37f9b Compare January 12, 2017 06:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants