Open brokenpylons opened 2 years ago
I later realized you could do:
type phantom = P
[@@deriving eq, ord, show]
type 'a t = Thing
[@@deriving eq, ord, show]
type usage = phantom t
[@@deriving eq, ord, show]
This way, it fills in the dummy argument and it still works. However, this solution is unsatisfactory, because the rest of the code still needs to account for this extra argument, so I'm reopening.
If t
isn't recursive (and thus its derived equal
isn't recursive), then you should be able to just do
type 'a t = Thing
[@@deriving eq]
let equal = equal (fun _ _ -> assert false) (* 'a doesn't occur in constructor args, so this function is never called *)
This doesn't work if you use this type inside another type and want to derive eq
again.
type phantom = P
[@@deriving eq]
type 'a t = Thing
[@@deriving eq]
let equal x y = equal (fun _ _ -> false) x y
type usage = phantom t
[@@deriving eq]
This fails with This expression should not be a function, the expected type is 'a t
.
type 'a t = Thing
[@@deriving eq]
let equal x y = equal (fun _ _ -> false) x y
type 'a usage = 'a t
[@@deriving eq]
This fails with This expression has type 'a -> 'a -> bool but an expression was expected of type 'b usage
.
I guess you could combine this with my previous solution:
type phantom = P
[@@deriving eq]
type 'a t = Thing
[@@deriving eq]
let equal' x y = equal (fun _ _ -> false) x y
type 'a usage = 'a t
[@@deriving eq]
let equal_usage' x y = equal_usage (fun _ _ -> false) x y
Is this the best that can be done?
type phantom = P
[@@deriving eq]
type 'a t = Thing
[@@deriving eq]
type 'a usage = 'a t
[@@deriving eq]
let equal = equal (fun _ _ -> assert false)
let equal_usage = equal_usage (fun _ _ -> assert false)
no need to define a new equal'
function if equal
is defined after the type definitions
I suspect this reveals why such support wouldn't fully work. Even if for type 'a t = Thing
we derive val equal: 'a t -> 'a t -> bool
, then whenever t
is used in another type that we want to derive for (e.g. in usage
), it is instantiated with one type parameter and thus val equal: ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
is assumed to exist instead. Subsequent uses of t
don't know that it's a phantom type parameter.
Couldn't you examine the type, to tell if the type parameters are phantom? I guess that wouldn't work if the type was abstract, though (maybe if you could somehow tag the parameter as phantom).
If the usage is in a separate module, I need to do something like the following, right?
module Thing = struct
module Deriving = struct
type phantom = P
[@@deriving eq]
type 'a t = Thing
[@@deriving eq]
end
include Deriving
let equal x y = equal (fun _ _ -> false) x y
end
module Usage = struct
module Deriving = struct
type 'a t = 'a Thing.Deriving.t
[@@deriving eq]
end
include Deriving
let equal x y = equal (fun _ _ -> false) x y
end
Is there a way to derive:
eq
,ord
,show
, for types that have a phantom type parameter? For example:The equals function generated for this type would have a signature
('a -> 'a -> bool) -> 'a t -> 'a t -> bool
, is there a way remove the first argument and generate just'a t -> 'a t -> bool
? The passed comparison function will never be used inside anyways.