i’m trying to compose two modules in a Module Function and i’d like for them to be able to expand a return type. i essence, im trying to do this:
module type T = {
type t<'a> = [> ] as 'a
}
module A: T = {
type t<'a> = [> #a] as 'a
}
module B: T = {
type t<'a> = [> #b] as 'a
}
module C = {
type t = [A.t | B.t]
let a: t = #b
}
but it’s giiving me this error:
42 │ }
43 │
44 │ module A: T = {
45 │ type t<'a> = [> #a] as 'a
46 │ }
47 │
48 │ module B: T = {
Signature mismatch:
Modules do not match:
{
type t<'a> = 'a
constraint 'a = [> #a]
}
is not included in
T
Type declarations do not match:
type t<'a> = 'a
constraint 'a = [> #a]
is not included in
type t<'a> = 'a
constraint 'a = [> ]
/home/spec1/Dropbox/desktop/rescript-homework/hw7/src/main.res:41:3-25:
Expected declaration
/home/spec1/Dropbox/desktop/rescript-homework/hw7/src/main.res:45:3-27:
Actual declaration
iirc i can do this in ocaml. am i doing it incorrectly or is pv across module boundaries just not possible in rescript?
module type T = {
type t
}
module A: T with type t = [#a] = {
type t = [ #a]
}
module B: T with type t = [#b] = {
type t = [ #b]
}
module C = {
type t = [A.t | B.t]
let a: t = #b
}
If you can come up with another solution in OCaml we can try to convert it together to rescript.
thanks, that’s clever and i didn’t know that was expressible, but that still doesn’t work with a Module Function that takes two Ts, which is what i’m doing.
well you could use the same technique with module functions but it’s rather similar:
module type T = {
type t
}
module Make = (A: T with type t = [#a], B: T with type t = [#b]) => {
type t = [A.t | B.t]
}
module C = Make(
{
type t = [#a]
},
{
type t = [#b]
},
)
i’m trying to compose two modules in a Module Function with polymorphic variants A.t and B.t to module C with C.t = [A.t|B.t] for the reason that they both have a PV return typ in A.tryMap and B.tryMap and i want to compose C so that C.tryMap = A.tryMap->B.tryMap so that the return type is expanded to include both, but that doesn’t seem to be expressible i think?
in rescript, there’s no way to express the fact that a type is of the kind of a generic variant, record, or polymorphic variant.
It’d be hard to implement anyway because in such cases, if you have no additional information on A.t or B.t, the compiler can’t know if there’s no overlapping variants between A.t and B.t when creating C.t for example :
to be able to compose two modules into one (for example, imagine JsonStringCodec and WhateverJsonCodec composed into WhateverStringCodec) so that i can use the one i need and don’t have to chain the calls everywhere, but that’s still trivially doable, just we can’t have a generic Compose Module Function for it
yeah i figured it’d be complex to implement and it’s a not-so-common scenario (module functions are underrated and underused tbh, they really serve a useful purpose especially with regard to DI).
and yeah, good point re. type ascription or skolemization or whatever it’s called when type is hidden behind module type T.