Chcę zdefiniować typ, tak aby cała konstrukcja przechodziła przez elementy modułu, które mogą zachować niezmienniki, ale zezwalać na destrukturyzację w celu dopasowania wzorca.Zachowanie niezmienności przy jednoczesnym umożliwieniu destrukturyzacji
Właśnie uczę SML ale po prawie działa dla int pary z niezmienna, że lewica powinna być ściśle mniej niż prawo
module Range : sig
type t = private { left:int; right:int }
exception InvalidRange of (int*int)
val make : int -> int -> t
end = struct
type t = { left:int; right:int }
exception InvalidRange of (int*int)
let make left right = if left < right
then { left; right }
else raise (InvalidRange (left, right))
end
który działa w ten sposób
# let p = Range.make 1 2;;
val p : Range.t = {Range.left = 1; Range.right = 2}
# let q = Range.make 2 1;;
Exception: Range.InvalidRange (2, 1).
i destrukturyzacja działa po mody
# let {Range.left=x; Range.right=y} = p;;
val x : int = 1
val y : int = 2
podczas konstruowania nie spełnia
# let badp = {Range.left = 2; Range.right = 1};;
let badp = {Range.left = 2; Range.right = 1};;
Error: Cannot create values of the private type Range.t
# open Range;;
# let badp = {left = 2; right=1};;
let badp = {left = 2; right=1};;
Error: Cannot create values of the private type Range.t
Ale naprawdę chciałbym zrobić, to mieć syntaktyczną wygodę destrukcji krotek. Poniższa nie działa:
module Range : sig
type t = private int*int
exception InvalidRange of (int*int)
val make : int -> int -> t
end = struct
type t = int*int
exception InvalidRange of (int*int)
let make left right = if left < right
then (left, right)
else raise (InvalidRange (left, right))
end
ale wtedy nie mogę destructure go za pomocą wzoru krotka:
# let r = Range.make 1 2 ;;
val r : Range.t = (1, 2)
# let (a, b) = r;;
let (a, b) = r;;
Error: This expression has type Range.t
but an expression was expected of type 'a * 'b
mogę zmienić typ do type t = R of (int * int)
ale muszę to być tak światło- w miarę możliwości należy pamiętać o wadze. Jakieś pomysły?
Dziękujemy za wskaźnik do instrukcji. Zajmie mi to trochę czasu, gdy zawiąże się między typem nominalnym a wymazanymi typami, a gdy nie. Czy obecność operatora wymuszania typu oznacza, że destrukturyzacja jest zawsze możliwa - więc nie ma możliwości ukrywania prawdziwych informacji (np. Mutables lub sekretów) za wyjątkiem wartości zamkniętych przez funkcje? –
Występuje różnica między 1) typami przezroczystymi, 2) typami abstrakcyjnymi, 3a) wariantami prywatnymi lub typami rekordów 3b) skrótami typu prywatnego. Dla 1) przymus jest możliwy w obie strony i jest niejawny. W przypadku 2) w ogóle nie jest możliwy przymus. W przypadku 3a) przymus jest możliwy w jedną stronę i wydaje się być ukryty. W przypadku 3b) przymus jest również możliwy w jedną stronę i wydaje się być wyraźny. Ważne jest, aby pamiętać, że koercjony nie mają zawartości obliczeniowej (są usuwane w czasie wykonywania). – esope
dzięki. Tak więc system typu jest dwuwarstwowy - fundamentalny, który ma rozróżnienie między typami konkretnymi i abstrakcyjnymi, który wpływa na wysyłkę wiadomości i powierzchowną, którą można usunąć, która może wykluczyć wysyłkę, ale nie ma na nią wpływu. –