I've got a range type defined as:
type 'a range = Full | Range of ('a * 'a)
However, I'd like to constrain 'a to be integer or float or char, with no other valid types for 'a.
Range(0,10) (* valid *)
Range(0.0, 10.0) (* valid *)
Range('a', 'z') (* valid *)
Range("string1", "string2") (* other types like this shouldn't type check *)
I figured that I could change my type definitions to:
type sequential = S_int of int | S_float of float | S_char of char ;;
type range = Full | Range of (sequential * sequential);;
However, this would then allow something like:
Range(S_int(0), S_float(10.0));; (* problem: mixes int and float *)
...but I want both components of Range to be the same type.
I suppose that another approach would be to create an int_range type, a float_range type, and a char_range type but I'm wondering if there's another way?
Another approach is to declare type private and expose functions constructing it only with the types you want, e.g. :
module Z : sig
type 'a range = private Full | Range of ('a * 'a)
val int_range : int -> int -> int range
val float_range : float -> float -> float range
val string_range : string -> string -> string range
val full : 'a range
end = struct
type 'a range = Full | Range of ('a * 'a)
let create x y = Range (x,y)
let int_range = create
let float_range = create
let string_range = create
let full = Full
end
# open Z;;
# int_range 2 3;;
- : int Z.range = Range (2, 3)
# Range ('a','c');;
Error: Cannot create values of the private type char Z.range
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With