2015-04-14 13 views
13

Proszę rozważyć następujący kod:Jaki jest sens Warning 40: ten rekord ... zawiera pola, które nie są widoczne w bieżącym zakresie

module A = 
    struct 
    type r = { i : int; s: string } 
    end 

module B = 
    struct 
    type r = { i : int; s : string } 
    end 


let f (x : A.r) : B.r = match x with 
    { i; s } -> { i = 2*i; s = "" } 

Dwa moduły definiują dokładnie ten sam rekord. Funkcja f konwertuje rekord A do rekordu B. Ostrzeżenie jest już emitowane podczas kompilacji, ale również widoczne interaktywnie. Na CLI SML, wydaje się, że wezwanie do f robi zamierzony rzecz:

# let x = f { i = 5; s = "ab" };; 
Characters 10-29: 
    let x = f { i = 5; s = "ab" };; 
      ^^^^^^^^^^^^^^^^^^^ 
Warning 40: this record of type Shadow.A.r contains fields that are 
not visible in the current scope: i s. 
They will not be selected if the type becomes unknown. 
val x : Shadow.B.r = {Shadow.B.i = 10; s = ""} 

znalazłem komentarz blogu na lexifi.com która wyjaśnia problem i pewne wspólne solutions. Czego nie rozumiem, to aktualny komunikat o błędzie:

  • Co to znaczy, że typ staje się nieznany?
  • Co to znaczy, gdy pole nie jest wybrane?
  • I wynikający z dwóch powyższych: jakie warunki należy spełnić, aby zignorować ostrzeżenie?

Odpowiedz

12

Typ rekordu jest znany w tym przypadku, ponieważ użytkownik dostarczył adnotacje. Po usunięciu adnotacji typ będzie nieznany, a znaczenie kodu może ulec zmianie.

Filozofią OCaml jest to, że dodawanie i usuwanie adnotacji typu nie powinno wpływać na znaczenie programu, dlatego generowane jest ostrzeżenie.

Możesz uniknąć tego ostrzeżenia, przenosząc odpowiednie pole do zakresu. Wykonanie tej czynności dla pola zdefiniowanego w module A pociąga za sobą albo otwarcie A, aby wprowadzić jego zawartość do zakresu, albo kwalifikowanie nazwy pola z modułem. Na przykład:

module A = struct ... end 

let test r = r.A.field 

let test2 r = let open A in r.field 

open A 

let test3 r = r.field 
+2

Tylko dla wyjaśnienia: muszę zakwalifikować się z modułem, w którym zdefiniowano rekord, a nie tym, który ma typ pola? (Przypuśćmy, że mam 'moduł C = typ struktury typu dummy = int end' i zmienię typ A.i i B.i na C.dummy, to nadal muszę się zakwalifikować z A i B, nie z C) –

+3

To prawda. – gsg

Powiązane problemy