W deklaracjach datatype
, Standard ML będzie generował typ równości, jeśli wszystkie argumenty typu dla wszystkich wariantów są same w sobie eqtype
s.Zapobiegaj, by typ SML nie stawał się typem eqtype bez ukrywania konstruktorów.
Widziałem komentarze w kilku miejscach lamentować niezdolność użytkowników do własnej definicji równości i konstruować własne eqtypes i nieoczekiwane konsekwencje zasad SML (np nagie ref
s i array
s są eqtypes, ale datatype Foo = Foo of (real ref)
nie jest typem eqty).
Źródło: http://mlton.org/PolymorphicEquality
można by oczekiwać, aby móc porównać dwie wartości typu rzeczywistym t, ponieważ porównanie wskaźnik na komórce ref wystarczy. Niestety, system typów może jedynie wyrazić, że typ danych zdefiniowany przez użytkownika dopuszcza równość lub nie.
Zastanawiam się, czy jest możliwe blok eqtyping. Załóżmy na przykład, że implementuję zestaw jako drzewo binarne (z niepotrzebnym wariantem) i chcę oddać możliwość strukturalnego porównywania zestawów ze sobą.
datatype 'a set = EmptySet | SetLeaf of 'a | SetNode of 'a * 'a set * 'a set;
powiedzieć, że nie chcemy, aby ludzie mogli odróżnić SetLeaf(5)
i SetNode(5, EmptySet, EmptySet)
z =
ponieważ jest to operacja abstrakcji łamanie.
Próbowałem prosty przykład z datatype on = On | Off
tylko po to, aby zobaczyć, czy mogę zdegradować typ do nie-eqtype za pomocą podpisów.
(* attempt to hide the "eq"-ness of eqtype *)
signature S = sig
type on
val foo : on
end
(* opaque transcription to kill eqtypeness *)
structure X :> S = struct
datatype on = On | Off
let foo = On
end
Wydaje się, że przejrzyste przypisywanie nie zapobiega X.on
od zostania eqtype, ale nieprzezroczyste przypisanie ma zapobiec. Jednak rozwiązania te nie są idealne, ponieważ wprowadzają nowy moduł i ukrywają konstruktory danych. Czy istnieje sposób, aby uniemożliwić konstruktorowi typu niestandardowego lub typu, aby stał się eqtype
lub przyznać równości bez ukrywania swoich konstruktorów danych lub wprowadzania nowych modułów?
R.e. Sprawa "bar", mój błąd. SML/NJ odrzuca opis typu "datatype", który opisujesz, ale w przypadku 'datatype foo = Foo of (real ref)' miałem na początku pytanie, że po prostu emituje nieprzyjemne ostrzeżenie o wywołaniu 'polyEqual'. –