I’m trying to write some Screeps bindings to play with Rescript, but I have some fundamental misunderstandings on how this all works.
There are many objects that are “Room Objects” in that they all have a room property and a position, and I tried to model that using the suggestion I received in Modelling Interfaces in ReScript - #2 by yawaramin and relying on module types:
type room
type pos
module type RoomObject = {
let room: room
let pos: roomPostion
}
module type Source = {
include RoomObject
let energy: float
let energyCapacity: float
let id: string
}
//...
which allows me to have a moveTo function typed as
Unfortunately, now I need to add a property to the room type that is also a room object! The Controller, and I can’t quite get the syntax right to pull this off (or if it even needs to be pulled off)…
Am I approaching this right? Is there maybe a better way to model this? Am I being too specific here? Any help would be super, thanks!
Update: the code so far for a clearer picture of what I’m trying to do.
A Source inherits the attributes of a RoomObject, therefore we provide a asRoomObject function that will give you access to the superset functionality of RoomObject.
Your final function would then look like this:
module Creep = {
type t
@send
external moveTo: (
t,
~target: RoomObject.t,
~opts: options=?,
unit,
) => abs_result = "moveTo"
}
Ugh of course! That actually simplifies a lot of things 🤦
Coming from Elixir, I’d probably try to use a Protocol for this to
automatically dispatch to the correct asRoomObject function.
defprotocol RoomObject do
def asRoomObject(object)
end
defimpl RoomObject, for: Source do
def asRoomObject(object), do: object
end
Is there a similar feature in ocaml/rescript? It is cool if not, but if
I could just get away with writing asRoomObject(thing) instead of Thing.asRoomObject(thing), I wouldn’t mind.
I think I could probably have a MakeRoomObject functor to at least
keep the repetitive-ness of writing external asRoomObject: t => RoomObject.t = "%identitiy" down
UPDATE: My functor:
and module MakeRoomObject: ('a) => IsRoomObject<'a> = (M: RO) => {
include M
external asRoomObject: t => RoomObject.t = "%identity"
}
and module Source: {
type t = {
energy: float,
energyCapacity: float,
id: string
}
} = MakeRoomObject({
type t = {
energy: float,
energyCapacity: float,
id: string
}
})
but because these are all recursive modules, I have no idea how to type the thing