Skip to content

Commit

Permalink
makeoption, tuples, nullable, etc. for union
Browse files Browse the repository at this point in the history
  • Loading branch information
jmagaram committed Apr 13, 2023
1 parent e50586b commit 14d902f
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 11 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
- `Option.map2`, `Option.map3`, `Option.map4` and test cleanup
- `Option.flatten`
- `Array.filterSome` and `Array.filterSomeWith`
- For untagged unions
- `Pattern.MakeOption` - Turn any pattern into a `t | undefined`
- `Pattern.MakeNullable` - Turn any pattern into a `t | undefined | null`
- `Pattern.MakeNull` - Turn any pattern into a `t | null`
- `Pattern.MakeTuple2` and `Pattern.MakeTuple3`
- Option to only show test failures

## Version 0.20.0
Expand Down
76 changes: 76 additions & 0 deletions src/Extras__Pattern.res
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,82 @@ module type T = {
let equals: (t, t) => bool
}

module MakeOption = (P: T) => {
type t = option<P.t>
let isTypeOf = v =>
switch v->Unknown.isUndefined {
| true => true
| false => P.isTypeOf(v)
}
let equals = (a, b) => Option.eq(a, b, P.equals)
}

module MakeNullable = (P: T) => {
type t = Js.Nullable.t<P.t>
let isTypeOf = (v: unknown) =>
switch v->Unknown.isNullOrUndefined {
| true => true
| false => P.isTypeOf(v->Unknown.make)
}
let equals = (a: t, b: t) => {
switch Unknown.isNull(a) {
| true => Unknown.isNull(b)
| false =>
switch Unknown.isUndefined(a) {
| true => Unknown.isUndefined(b)
| false => !Unknown.isNullOrUndefined(b) && P.equals(a->Obj.magic, b->Obj.magic)
}
}
}
}

module MakeNull = (P: T) => {
type t = Js.Null.t<P.t>
let isTypeOf = (v: unknown) =>
switch v->Unknown.isNull {
| true => true
| false => P.isTypeOf(v->Unknown.make)
}
let equals = (a: t, b: t) =>
switch a->Unknown.isNull {
| true => b->Unknown.isNull
| false => !(b->Unknown.isNull) && P.equals(a->Obj.magic, b->Obj.magic)
}
}

module MakeTuple2 = (
P: {
module A: T
module B: T
},
) => {
type t = (P.A.t, P.B.t)
let isTypeOf = (u: unknown) =>
u->Js.Array2.isArray &&
u->Obj.magic->Js.Array2.length == 2 &&
P.A.isTypeOf(u->Obj.magic->Js.Array2.unsafe_get(0)) &&
P.B.isTypeOf(u->Obj.magic->Js.Array2.unsafe_get(1))
let equals = ((a1, b1): t, (a2, b2): t) => P.A.equals(a1, a2) && P.B.equals(b1, b2)
}

module MakeTuple3 = (
P: {
module A: T
module B: T
module C: T
},
) => {
type t = (P.A.t, P.B.t, P.C.t)
let isTypeOf = (u: unknown) =>
u->Js.Array2.isArray &&
u->Obj.magic->Js.Array2.length == 3 &&
P.A.isTypeOf(u->Obj.magic->Js.Array2.unsafe_get(0)) &&
P.B.isTypeOf(u->Obj.magic->Js.Array2.unsafe_get(1)) &&
P.C.isTypeOf(u->Obj.magic->Js.Array2.unsafe_get(2))
let equals = ((a1, b1, c1): t, (a2, b2, c2): t) =>
P.A.equals(a1, a2) && P.B.equals(b1, b2) && P.C.equals(c1, c2)
}

module MakeTools = (P: T) => {
let make = x => x->Unknown.make->P.isTypeOf ? Some((Obj.magic(x): P.t)) : None
let eq = (x, y) => x->make->Option.flatMap(x => y->make->Option.map(y => P.equals(x, y)))
Expand Down
39 changes: 39 additions & 0 deletions src/Extras__Pattern.resi
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,45 @@ module type T = {
let equals: (t, t) => bool
}

/**
Given a `Pattern.T`, construct a pattern corresponding to an option of that
type. An option maps to `undefined | T`
*/
module MakeOption: (P: T) => (T with type t = option<P.t>)

/**
Given a `Pattern.T`, construct a pattern corresponding to a `null | undefined |
t` of that type.
*/
module MakeNullable: (P: T) => (T with type t = Js.Nullable.t<P.t>)

/**
Given a `Pattern.T`, construct a pattern corresponding to a `null | t` of that
type.
*/
module MakeNull: (P: T) => (T with type t = Js.Null.t<P.t>)

/**
Given two patterns, construct a tuple pattern (array of length 2).
*/
module MakeTuple2: (
P: {
module A: T
module B: T
},
) => (T with type t = (P.A.t, P.B.t))

/**
Given three patterns, construct a tuple pattern (array of length 3).
*/
module MakeTuple3: (
P: {
module A: T
module B: T
module C: T
},
) => (T with type t = (P.A.t, P.B.t, P.C.t))

/**
Given a `Pattern.T`, constructs some utility functions.
*/
Expand Down
Loading

0 comments on commit 14d902f

Please sign in to comment.