Skip to content

Commit a65ebf5

Browse files
Changed the return type of validate to Either (Array ValidationError) a
This commit adds two extra functions, a curried `map` and `lefts`. There is plenty of room for optimization but we should validate the concept with a simple example application before optimizing.
1 parent d404784 commit a65ebf5

File tree

2 files changed

+110
-107
lines changed

2 files changed

+110
-107
lines changed

index.js

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@
220220
// Right :: b -> Either a b
221221
var Right = Either.Right;
222222

223+
// lefts :: Fola
224+
var lefts = B (map (prop ('value'))) (filter (prop ('isLeft')));
225+
223226
// B :: (b -> c) -> (a -> b) -> a -> c
224227
function B(f) {
225228
return function(g) {
@@ -252,11 +255,11 @@
252255
}
253256

254257
// map :: Functor f => (a -⁠> b) -⁠> f a -⁠> f b
255-
// function map(f) {
256-
// return function(xs) {
257-
// return Z.map (f, xs);
258-
// };
259-
// }
258+
function map(f) {
259+
return function(xs) {
260+
return Z.map (f, xs);
261+
};
262+
}
260263

261264
// init :: Array a -> Array a
262265
function init(xs) { return xs.slice (0, -1); }
@@ -1506,26 +1509,19 @@
15061509
};
15071510
}
15081511

1509-
//# validate :: Type -> a -> Array (Either Object a)
1512+
//# validate :: Type -> a -> Either (Array ValidationError) a
15101513
//.
1511-
//. Takes a type, and any value. Returns an `Array` of
1512-
//. `Right a` if the value is a member of the type;
1513-
//. `Left Object` for each property that is invalid.
1514-
//. The first index in an array of `Left`s is always named `$$`,
1515-
//. which refers to the entire value.
1514+
//. Takes a type, and any value. Returns `Right a` if
1515+
//. the value is a member of the type;
1516+
//. `Left (Array ValidationError)` for each property
1517+
//. that is invalid. The first index in a `Left` array
1518+
//. is always named `$$`, which refers to the entire value.
15161519
function validate(t) {
15171520
return function(x) {
1518-
// 1. build list of prop, validate function and value object for all keys
1519-
// 2. when value = null, use MissingValue object
1520-
// 3. run all remainder validate functions for nested type validation
1521-
// 4. remove all Rights from list
1522-
// 5. concatenate $$ (in returnValue) with all Lefts
1523-
1524-
var returnValue = [];
1525-
var $$Result = t.validate ([]) (x);
1521+
// $$Result :: {value, propPath} e => Either e a
1522+
var $$Result = t.validate ([]) (x);
15261523

1527-
// 1 and 2
1528-
// props :: Array (Either Object Object)
1524+
// props :: Array (Either ValidationError TestObject)
15291525
var props = t.keys.map (function(p) {
15301526
return x == null
15311527
? Left ({
@@ -1541,8 +1537,11 @@
15411537
});
15421538
});
15431539

1544-
var validateRights = Z.compose (function(p) {
1545-
if (p.result.isLeft) {
1540+
// validateTestObject :: TestObject -> Either ValidationError TestObject
1541+
var validateTestObject = Z.compose (function(p) {
1542+
if (p.result.isRight) {
1543+
return Right (p);
1544+
} else {
15461545
if (p.name in x) {
15471546
return Left ({
15481547
error: 'WrongValue',
@@ -1561,8 +1560,6 @@
15611560
value: p.value
15621561
});
15631562
}
1564-
} else {
1565-
return Right (p);
15661563
}
15671564
}, function(p) {
15681565
return {
@@ -1573,29 +1570,35 @@
15731570
};
15741571
});
15751572

1576-
returnValue.push (
1577-
$$Result.isLeft
1578-
? Left ({
1579-
error: 'WrongValue',
1580-
type: t.name || t.type,
1581-
name: '$$',
1582-
value: x
1583-
})
1584-
: $$Result
1585-
);
1586-
1587-
// 3
1588-
var tmp0 = Z.map (function(prop) {
1589-
return Z.chain (validateRights, prop);
1590-
}, props);
1591-
1592-
// 4
1593-
var tmp1 = Z.filter (function(either) {
1594-
return either.isLeft;
1595-
}, tmp0);
1573+
if ($$Result.isLeft) {
1574+
// tmp0 :: Array (Either ValidationError TestObject)
1575+
var tmp0 = Z.map (function(prop) {
1576+
return Z.chain (validateTestObject, prop);
1577+
}, props);
1578+
1579+
// tmp1 :: Array (Left ValidationError)
1580+
var tmp1 = Z.filter (function(either) {
1581+
return either.isLeft;
1582+
}, tmp0);
1583+
1584+
// tmp2 :: Array (Left ValidationError)
1585+
var tmp2 = Z.prepend (Left ({
1586+
error: 'WrongValue',
1587+
type: t.name || t.type,
1588+
name: '$$',
1589+
value: x
1590+
}), tmp1);
1591+
1592+
// tmp3 :: Array (ValidationError)
1593+
var tmp3 = lefts (tmp2);
1594+
1595+
// return :: Left (Array ValidationError)
1596+
return Left (tmp3);
1597+
} else {
1598+
// return :: Right a
1599+
return $$Result;
1600+
}
15961601

1597-
// 5
1598-
return Z.concat (returnValue, tmp1);
15991602
// return Z.concat (
16001603
// returnValue,
16011604
// Z.filter (
@@ -3015,7 +3018,7 @@
30153018
validate:
30163019
def ('validate')
30173020
({})
3018-
([Type, Any, Array_ (Either_ (Object_) (Any))])
3021+
([Type, Any, Either_ (Array_ (Object_)) (Any)])
30193022
(validate),
30203023
NullaryType:
30213024
def ('NullaryType')

test/index.js

Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3883,7 +3883,7 @@ suite ('validate', () => {
38833883
test ('Undefined', () => {
38843884

38853885
eq ($.validate ($.Undefined) (undefined))
3886-
([Right (undefined)]);
3886+
(Right (undefined));
38873887

38883888
});
38893889

@@ -3898,53 +3898,53 @@ suite ('validate', () => {
38983898

38993899
// null is not a member of ‘FooBar’
39003900
eq ($.validate (FooBar) (null))
3901-
([
3902-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': null}),
3903-
Left ({'error': 'MissingValue', 'name': 'bar', 'type': 'FooBar', 'value': null}),
3904-
Left ({'error': 'MissingValue', 'name': 'foo', 'type': 'FooBar', 'value': null}),
3905-
]);
3901+
(Left ([
3902+
{'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': null},
3903+
{'error': 'MissingValue', 'name': 'bar', 'type': 'FooBar', 'value': null},
3904+
{'error': 'MissingValue', 'name': 'foo', 'type': 'FooBar', 'value': null},
3905+
]));
39063906

39073907
// undefined is not a member of ‘FooBar’
39083908
eq ($.validate (FooBar) (undefined))
3909-
([
3910-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': undefined}),
3911-
Left ({'error': 'MissingValue', 'name': 'bar', 'type': 'FooBar', 'value': undefined}),
3912-
Left ({'error': 'MissingValue', 'name': 'foo', 'type': 'FooBar', 'value': undefined}),
3913-
]);
3909+
(Left ([
3910+
{'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': undefined},
3911+
{'error': 'MissingValue', 'name': 'bar', 'type': 'FooBar', 'value': undefined},
3912+
{'error': 'MissingValue', 'name': 'foo', 'type': 'FooBar', 'value': undefined},
3913+
]));
39143914

39153915
// ''bar' field is missing', ''foo' field is missing'
39163916
eq ($.validate (FooBar) ({}))
3917-
([
3918-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': {}}),
3919-
Left ({'error': 'MissingValue', 'name': 'bar', 'type': 'Number', 'value': undefined}),
3920-
Left ({'error': 'MissingValue', 'name': 'foo', 'type': 'String', 'value': undefined}),
3921-
]);
3917+
(Left ([
3918+
{'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': {}},
3919+
{'error': 'MissingValue', 'name': 'bar', 'type': 'Number', 'value': undefined},
3920+
{'error': 'MissingValue', 'name': 'foo', 'type': 'String', 'value': undefined},
3921+
]));
39223922

39233923
// 'bar' field is missing
39243924
eq ($.validate (FooBar) ({foo: null}))
3925-
([
3926-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': {'foo': null}}),
3927-
Left ({'error': 'MissingValue', 'name': 'bar', 'type': 'Number', 'value': undefined}),
3928-
Left ({'error': 'WrongValue', 'name': 'foo', 'type': 'String', 'value': null}),
3929-
]);
3925+
(Left ([
3926+
{'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': {'foo': null}},
3927+
{'error': 'MissingValue', 'name': 'bar', 'type': 'Number', 'value': undefined},
3928+
{'error': 'WrongValue', 'name': 'foo', 'type': 'String', 'value': null},
3929+
]));
39303930

39313931
// Value of 'bar' field, null, is not a member of ‘Number’
39323932
eq ($.validate (FooBar) ({foo: null, bar: null}))
3933-
([
3934-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': {'bar': null, 'foo': null}}),
3935-
Left ({'error': 'WrongValue', 'name': 'bar', 'type': 'Number', 'value': null}),
3936-
Left ({'error': 'WrongValue', 'name': 'foo', 'type': 'String', 'value': null}),
3937-
]);
3933+
(Left ([
3934+
{'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': {'bar': null, 'foo': null}},
3935+
{'error': 'WrongValue', 'name': 'bar', 'type': 'Number', 'value': null},
3936+
{'error': 'WrongValue', 'name': 'foo', 'type': 'String', 'value': null},
3937+
]));
39383938

39393939
// Value of 'foo' field, null, is not a member of ‘String’
39403940
eq ($.validate (FooBar) ({foo: null, bar: 42}))
3941-
([
3942-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': {'bar': 42, 'foo': null}}),
3943-
Left ({'error': 'WrongValue', 'name': 'foo', 'type': 'String', 'value': null}),
3944-
]);
3941+
(Left ([
3942+
{'error': 'WrongValue', 'name': '$$', 'type': 'FooBar', 'value': {'bar': 42, 'foo': null}},
3943+
{'error': 'WrongValue', 'name': 'foo', 'type': 'String', 'value': null},
3944+
]));
39453945

39463946
eq ($.validate (FooBar) ({foo: 'blue', bar: 42}))
3947-
([Right ({foo: 'blue', bar: 42})]);
3947+
(Right ({foo: 'blue', bar: 42}));
39483948

39493949
});
39503950

@@ -3968,48 +3968,48 @@ suite ('validate', () => {
39683968
});
39693969

39703970
eq ($.validate (model1) ({date: '2020-04-10'}))
3971-
([Right ({date: '2020-04-10'})]);
3971+
(Right ({date: '2020-04-10'}));
39723972

39733973
eq ($.validate (model1) ({date: '2020-04-100'}))
3974-
([
3975-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'date': '2020-04-100'}}),
3976-
Left ({'error': 'WrongValue', 'name': 'date', 'type': 'DateIso', 'value': '2020-04-100'}),
3977-
]);
3974+
(Left ([
3975+
{'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'date': '2020-04-100'}},
3976+
{'error': 'WrongValue', 'name': 'date', 'type': 'DateIso', 'value': '2020-04-100'},
3977+
]));
39783978

39793979
eq ($.validate (model2) (undefined))
3980-
([
3981-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': undefined}),
3982-
Left ({'error': 'MissingValue', 'name': 'date', 'type': 'RECORD', 'value': undefined}),
3983-
Left ({'error': 'MissingValue', 'name': 'bool', 'type': 'RECORD', 'value': undefined}),
3984-
]);
3980+
(Left ([
3981+
{'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': undefined},
3982+
{'error': 'MissingValue', 'name': 'date', 'type': 'RECORD', 'value': undefined},
3983+
{'error': 'MissingValue', 'name': 'bool', 'type': 'RECORD', 'value': undefined},
3984+
]));
39853985

39863986
eq ($.validate (model2) ({bool: 'foobar', date: '2020-04-100'}))
3987-
([
3988-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'bool': 'foobar', 'date': '2020-04-100'}}),
3989-
Left ({'error': 'WrongValue', 'name': 'date', 'type': 'DateIso', 'value': '2020-04-100'}),
3990-
Left ({'error': 'WrongValue', 'name': 'bool', 'type': 'Boolean', 'value': 'foobar'}),
3991-
]);
3987+
(Left ([
3988+
{'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'bool': 'foobar', 'date': '2020-04-100'}},
3989+
{'error': 'WrongValue', 'name': 'date', 'type': 'DateIso', 'value': '2020-04-100'},
3990+
{'error': 'WrongValue', 'name': 'bool', 'type': 'Boolean', 'value': 'foobar'},
3991+
]));
39923992

39933993
eq ($.validate (model2) ({date: '2020-04-10', bool: 'foobar'}))
3994-
([
3995-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'bool': 'foobar', 'date': '2020-04-10'}}),
3996-
Left ({'error': 'WrongValue', 'name': 'bool', 'type': 'Boolean', 'value': 'foobar'}),
3997-
]);
3994+
(Left ([
3995+
{'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'bool': 'foobar', 'date': '2020-04-10'}},
3996+
{'error': 'WrongValue', 'name': 'bool', 'type': 'Boolean', 'value': 'foobar'},
3997+
]));
39983998

39993999
eq ($.validate (model2) ({date: '2020-04-100', bool: true}))
4000-
([
4001-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'bool': true, 'date': '2020-04-100'}}),
4002-
Left ({'error': 'WrongValue', 'name': 'date', 'type': 'DateIso', 'value': '2020-04-100'}),
4003-
]);
4000+
(Left ([
4001+
{'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'bool': true, 'date': '2020-04-100'}},
4002+
{'error': 'WrongValue', 'name': 'date', 'type': 'DateIso', 'value': '2020-04-100'},
4003+
]));
40044004

40054005
eq ($.validate (model2) ({date: [], bool: false}))
4006-
([
4007-
Left ({'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'bool': false, 'date': []}}),
4008-
Left ({'error': 'WrongValue', 'name': 'date', 'type': 'NonEmpty', 'value': []}),
4009-
]);
4006+
(Left ([
4007+
{'error': 'WrongValue', 'name': '$$', 'type': 'RECORD', 'value': {'bool': false, 'date': []}},
4008+
{'error': 'WrongValue', 'name': 'date', 'type': 'NonEmpty', 'value': []},
4009+
]));
40104010

40114011
eq ($.validate (model2) ({bool: false, date: '2020-04-10'}))
4012-
([Right ({date: '2020-04-10', bool: false})]);
4012+
(Right ({date: '2020-04-10', bool: false}));
40134013

40144014
});
40154015

0 commit comments

Comments
 (0)