`tagged` can't accept an unkeyed value
Sometimes, one wants to just decorate a value with a type. It can feel a little redundant with tagged
to key value
as { value }
This was possible with nFold
(which I just removed because I never used it).
I guess in these cases it's not hard to just define the sum-type on your own. A real world use case:
const Credit = {
name: 'Credit'
,Insufficient:
value => ({ type: 'Credit', case: 'Insufficient', value })
,Warning:
value => ({ type: 'Credit', case: 'Warning', value })
,Healthy:
value => ({ type: 'Credit', case: 'Healthy', value })
}
The actual information here is: type:Credit, cases:Insufficient,Warning,Healthy
.
Which could be represented pretty easily with the previous nFold
API:
sst.nFold ('Credit') (['Insufficient', 'Warning', 'Healthy'])
However, I so rarely used this. I feel justified in removing it.
Maybe there's a way to make tagged
a little more general.
Could be a bunch of combinators.
E.g. a normal tagged could be created with a constructor that assumed a record with certain cases.
tagged ('Shape') ({
Point: ['x', 'y'],
Line: ['p1', 'p2']
})
Could become:
tagged ('Shape') ({
Point: record(['x', 'y']),
Line: record(['p1', 'p2'])
})
Which opens doors for creating custom case validators. E.g.
tagged ('Credit') ({
Insufficient: sst.any(),
Warning: sst.any(),
Healthy: sst.any()
})
Maybe the decorator can apply to all cases. E.g.
tagged (any) ('Credit') ({
Insufficient: [],
Warning: [],
Healthy: []
})
tagged (record) ('Shape') ({
Point: ['x', 'y'],
Line: ['p1', 'p2']
})
Where said decorator, was passed something like typeName => caseName => caseInput
In the case of Shape.Point
that might look like record ('Shape') ('Point') (['x', 'y'])
In the case of any
it might look like this any ('Credit') ('Insufficient') ([])
A decorator could be defined to simply return a value constructor/transformer, like so:
const decorator = typeName => caseName => caseInput => {
// validations + transformations based on caseInput
return value => value
}
The reason typeName
and caseName
are passed in, would be to include names in the assertions when an error is thrown.
The library could internally use this pattern and export taggedRecord
and tagged
separately. I'm not sure though, I like how simple this case is, and I feel the complexity isn't worth it when it's simple enough to manually write the type out by hand. It's maybe something to consider if this keeps cropping up.