fp-ts
fp-ts copied to clipboard
extended Bounded type
Extends Bounded type. It's currently a work in progress, but I am looking for feedback. The thinking with these functions is that Bounded effectively represents a range of values. So, testing whether a value is within a range, if ranges overlap, clamping a value to a range, etc., makes sense.
import * as n from 'fp-ts/number';
import { top, bottom, fromRange, isWithin, clamp, toTuple } from 'fp-ts/Bounded';
const bound = fromRange(n.Ord)(0)(10);
top(bound) // 0
bottom(bound) //10
isWithin(bound)(1) //true
isWithin(bound)(11) //false
toTuple(bound) // [0, 10]
clamp(bound)(12) // 10
Fixed issues.
Looks good. Just another idea when creating a Bound
why not have a function that always returns a valid bound like your fromRange
but one that never fails.
export const bounded = <T>(O: Ord.Ord<T>) => (b: T) => (t: T): Bounded<T> =>
Ord.geq(O)(B.bottom, B.top) ? ({ ...O, bottom: b, top: t }) : ({ ...O, bottom: t, top: b })
What do you think?
Thanks! Hmm. This seems useful; although, I can't quite imagine a use case for it at the moment. Maybe called something like coerceBound to clarify that the order might not be the same as the order of the provided arguments?
Added coerceBound, reverse, and isEmpty. Although, isEmpty might not be the best name for this function as a bound where top === bottom has exactly one value that is within the bound. Any thoughts? I'm leaning towards isSingular, isFlat, or isClosed.
Use case for me would be as smart constructor where I do not care about validation and just want a valid Bounded
.
I find isSingular
a good choice.
Ok. I like the idea of a smart constructor. And isSingular is a good name. I updated the pr. Is there anything else that you can think of that needs changing?
Fixed.
Hmm. Any idea what might be up with the automated testing? It seems like an issue with prettier but running prettier --write doesn't fix the issue and the error message isn't specific enough. Also, I'm considering adding a function that constructs a Bounded type from an instance of Ord and a ReadonlyNonEmptyArray of values. What are your thoughts? Something like this:
import * as A from 'fp-ts/ReadonlyNonEmptyArray';
import * as T from 'fp-ts/Tuple';
import * as n from 'fp-ts/number';
import { Bounded } from 'fp-ts/Bounded';
import { Ord } from 'fp-ts/Ord';
import { pipe } from 'fp-ts/function';
const fromArray = <X>(ord: Ord<X>) => (arr: A.ReadonlyNonEmptyArray<X>) => pipe(
arr,
x => [x, x] as [A.ReadonlyNonEmptyArray<X>, A.ReadonlyNonEmptyArray<X>],
T.bimap(A.max(ord), A.min(ord)), // [min, max]
t => ({ ...ord, bottom: t[0], top: t[1] }) as Bounded<X>
)
// Returns instance of Bounded where { bottom: 1, top: 5 }
fromArray(n.Ord)([1, 2, 3, 4, 5])