Skip to content

Commit

Permalink
work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
davidchambers committed Jun 19, 2021
1 parent e5ea023 commit 778b4a2
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 1 deletion.
61 changes: 60 additions & 1 deletion index.js
Expand Up @@ -345,6 +345,7 @@
if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = f (require ('sanctuary-def'),
require ('sanctuary-either'),
require ('sanctuary-identity'),
require ('sanctuary-maybe'),
require ('sanctuary-pair'),
require ('sanctuary-show'),
Expand All @@ -353,6 +354,7 @@
} else if (typeof define === 'function' && define.amd != null) {
define (['sanctuary-def',
'sanctuary-either',
'sanctuary-identity',
'sanctuary-maybe',
'sanctuary-pair',
'sanctuary-show',
Expand All @@ -362,14 +364,15 @@
} else {
self.sanctuary = f (self.sanctuaryDef,
self.sanctuaryEither,
self.sanctuaryIdentity,
self.sanctuaryMaybe,
self.sanctuaryPair,
self.sanctuaryShow,
self.sanctuaryTypeClasses,
self.sanctuaryTypeIdentifiers);
}

} (function($, Either, Maybe, Pair, show, Z, type) {
} (function($, Either, Identity, Maybe, Pair, show, Z, type) {

'use strict';

Expand Down Expand Up @@ -4748,6 +4751,62 @@
impl: splitOnRegex
};

//. ### Lens

//# lens :: TK
//.
//. TK.
//.
//. ```javascript
//. > S.toUpper ('ABC def 123')
//. 'ABC DEF 123'
//. ```
function lens(getter) {
return function(setter) {
return function(f) {
return function(s) {
return Z.map (
function(v) { return setter (v) (s); },
f (getter (s))
);
};
};
};
}
_.lens = {
consts: {},
types: function(s) {
return [$.Fn (s) (a), $.Fn (a) ($.Fn (s) (s)), $.Any];
} ($.TypeVariable ('s')),
impl: lens
};

//# view :: TK
function view(lens) {
return function(x) {
return (lens (Left) (x)).value;
};
}
_.view = {
consts: {},
types: [$.Any, $.Any, $.Any],
impl: view
};

//# over :: TK
function over(lens) {
return function(f) {
return function(x) {
return Z.extract (lens (function(y) { return Identity (f (y)); }) (x));
};
};
}
_.over = {
consts: {},
types: [$.Any, $.Any, $.Any, $.Any],
impl: over
};

return create ({
checkTypes: typeof process === 'undefined'
|| process == null
Expand Down
12 changes: 12 additions & 0 deletions test/lens.js
@@ -0,0 +1,12 @@
'use strict';

const S = require ('..');

const eq = require ('./internal/eq');


test ('lens', () => {

eq (S.show (S.lens)) ('lens :: (s -> a) -> (a -> s -> s) -> Any');

});
31 changes: 31 additions & 0 deletions test/over.js
@@ -0,0 +1,31 @@
'use strict';

const S = require ('..');

const eq = require ('./internal/eq');


test ('over', () => {

eq (S.show (S.over)) ('over :: Any -> Any -> Any -> Any');

const snd = S.lens (S.snd) (x => S.map (S.K (x)));
const fahrenheit = S.lens (c => c * 9 / 5 + 32) (f => c => (f - 32) * 5 / 9);

// Increase the temperature in San Francisco by 1 °C
eq (S.over (snd) (S.add (1)) (S.Pair ('San Francisco') (20)))
(S.Pair ('San Francisco') (21));

// 1 °F above freezing, in °C
eq (S.over (fahrenheit) (S.add (1)) (0)) (0.5555555555555556);

// 1 °F above freezing, in °F
eq (S.view (fahrenheit) (S.over (fahrenheit) (S.add (1)) (0))) (33);

// Decrease the temperature in San Francisco by 4 °F
eq (S.over (S.compose (snd) (fahrenheit))
(S.sub (4))
(S.Pair ('San Francisco') (20)))
(S.Pair ('San Francisco') (17.77777777777778));

});
12 changes: 12 additions & 0 deletions test/set.js
@@ -0,0 +1,12 @@
'use strict';

const S = require ('..');

const eq = require ('./internal/eq');


test ('set', () => {

eq (S.show (S.set)) ('set :: TK');

});
31 changes: 31 additions & 0 deletions test/view.js
@@ -0,0 +1,31 @@
'use strict';

const S = require ('..');

const eq = require ('./internal/eq');


test ('view', () => {

eq (S.show (S.view)) ('view :: Any -> Any -> Any');

const snd = S.lens (S.snd) (x => S.map (S.K (x)));
const fahrenheit = S.lens (c => c * 9 / 5 + 32) (f => c => (f - 32) * 5 / 9);

eq (S.view (snd) (S.Pair ('San Francisco') (20))) (20);

eq (S.view (fahrenheit) (0)) (32);
eq (S.view (fahrenheit) (50)) (122);
eq (S.view (fahrenheit) (100)) (212);

// Temperature in San Francisco, converted to °F
eq (S.view (S.compose (snd) (fahrenheit))
(S.Pair ('San Francisco') (20)))
(68);

// Lenses compose via function composition
eq (S.view (x => snd (fahrenheit (x)))
(S.Pair ('San Francisco') (20)))
(68);

});

0 comments on commit 778b4a2

Please sign in to comment.