2010-06-25 11 views
10

OCaml 컴파일러가 제공하는 경고를 수정하는 데 문제가 있습니다.OCaml에서 철저한 일치 경고를 표시하지 않습니다.

기본적으로 나는 Bool, IntFloat으로 구성 될 수있는 표현식을 구문 분석합니다.

나는 자신의 유형으로 선언 된 모든 기호를 추적하는 심볼 테이블이 있습니다 int 모든 변수의 배열에서 나중에 사용되는 인덱스입니다

type ast_type = Bool | Int | Float 
and variables = (string, int*ast_type) Hashtbl.t; 

.

type value = 
    | BOOL of bool 
    | INT of int 
    | FLOAT of float 
    | UNSET 
and var_values = value array 

나는 내가 너무 무엇을 부울 식 내부 변수 참조의 동작을 정의하기 위해 노력하고있어

    입니다 :

    나는 변수의 값을 나타내는 구체적인 유형은 다음이 변수 변수 BOOL

입력을 가지고
  • 검사를 선언되었는지 체크
  • | GVar s -> 
          begin 
           try 
            let (i,t) = Hashtbl.find variables s in 
             if (t != Bool) then 
              raise (SemanticException (BoolExpected,s)) 
             else 
              (fun s -> let BOOL v = Array.get var_values i in v) 
           with 
            Not_found -> raise (SemanticException (VarUndefined,s)) 
          end 
    

    문제는 내 검사 var_values에서 가져온 요소가이 제약 ISN '유형 BOOL of bool으로하지만 당연히 될 것이라고 확신이다 :

    내가 (s은 변수의 이름입니다)이 코드가이 작업을 수행하는 컴파일러가 나를 경고하는 t :

    경고 P :이 패턴 일치는 완전한 것이 아닙니다. 나는 문제의이 종류를 해결하기 위해 가정하고 어떻게

    (| | INT _ UNSET FLOAT _) : 여기 는 일치하지 않는 값의 예입니다? 미리 감사드립니다.

  • +0

    'var_values ​​= value array' 형식을 선언하는 것은 유용 할뿐입니다.이 형식을 추상화하고 그 이름 만 모듈 외부에서 볼 수있게하면 유용합니다. 이 가능성을 제외하고는 오류 메시지를 읽기 쉽게 만들 수있는 쓸모없는 유형 별칭입니다. –

    답변

    8

    이것은 당신이 OCaml's polymorphic variants를 사용하여 해결할 수있는 문제입니다. 그것은 경고를 생성

    type ast_type = Bool | Int | Float 
    and variables = (string, int*ast_type) Hashtbl.t 
    
    type value = 
        | BOOL of bool 
        | INT of int 
        | FLOAT of float 
        | UNSET 
    
    and var_values = value array 
    
    type expr = GVar of string 
    
    type exceptioninfo = BoolExpected | VarUndefined 
    
    exception SemanticException of exceptioninfo * string 
    
    let variables = Hashtbl.create 13 
    
    let var_values = Array.create 13 (BOOL false) 
    
    let f e = 
        match e with 
        | GVar s -> 
        begin 
         try 
         let (i,t) = Hashtbl.find variables s in 
          if (t != Bool) then 
          raise (SemanticException (BoolExpected,s)) 
          else 
          (fun s -> let BOOL v = Array.get var_values i in v) 
         with 
         Not_found -> raise (SemanticException (VarUndefined,s)) 
        end 
    

    :

    File "t.ml", line 30, characters 42-48: 
    Warning P: this pattern-matching is not exhaustive. 
    Here is an example of a value that is not matched: 
    (FLOAT _|INT _|UNSET) 
    

    여기 다형 변종을 사용하여 변형 같은 코드 여기

    내가 전시에게 문제를 추론 일부 컴파일 가능한 OCaml의 코드입니다. 이 코드는 경고없이 컴파일됩니다. 다형성 변형은 표준 유형보다 표현력이 더 뛰어납니다 (여기에서 var_valuesBOOL의 배열 임).하지만 경고문이 혼란 스러울 수 있습니다. 여기
    type ast_type = Bool | Int | Float 
    and variables = (string, int*ast_type) Hashtbl.t 
    
    type value = 
        [ `BOOL of bool 
        | `INT of int 
        | `FLOAT of float 
        | `UNSET ] 
    
    and var_values = value array 
    
    type expr = GVar of string 
    
    type exceptioninfo = BoolExpected | VarUndefined 
    
    exception SemanticException of exceptioninfo * string 
    
    let variables = Hashtbl.create 13 
    
    let var_values = Array.create 13 (`BOOL false) 
    
    let f e = 
        match e with 
        | GVar s -> 
        begin 
         try 
         let (i,t) = Hashtbl.find variables s in 
          if (t != Bool) then 
          raise (SemanticException (BoolExpected,s)) 
          else 
          (fun s -> let `BOOL v = Array.get var_values i in v) 
         with 
         Not_found -> raise (SemanticException (VarUndefined,s)) 
        end 
    

    는 상기 코드를 OCaml 유추 종류 파스칼에 의해 설명 된 바와 같이 특히이 경우

    type ast_type = Bool | Int | Float 
    and variables = (string, int * ast_type) Hashtbl.t 
    type value = [ `BOOL of bool | `FLOAT of float | `INT of int | `UNSET ] 
    and var_values = value array 
    type expr = GVar of string 
    type exceptioninfo = BoolExpected | VarUndefined 
    exception SemanticException of exceptioninfo * string 
    val variables : (string, int * ast_type) Hashtbl.t 
    val var_values : [ `BOOL of bool ] array 
    val f : expr -> 'a -> bool 
    
    4

    this에서 "경고 사용 안함"을 검색하십시오. 깃발 -w에 와야합니다.

    "ocamlish"방법으로 수정하려면 패턴 일치를 철저히해야합니다. 즉, 발생할 수있는 모든 사례를 포괄해야합니다.

    그러나 가능한 모든 값과 일치하지 않으려면 명시 적으로 처리하지 않으려는 모든 경우를 다루는 와일드 카드 (here 참조)를 사용하는 것이 좋습니다.

    +0

    예,이 방법이 도움이 될 수 있지만 경고를 안전하게 비활성화하지 않고 안전하게 해결할 수있는 방법이 있습니까? – Jack

    +2

    @Jack True OCamlish Way는 사용되지 않는 값이 존재하지 않도록 데이터 형식을 작성합니다. 그러나 이것이 항상 실용적이거나 바람직한 것은 아닙니다. 두 번째는 예외 ("Invalid_argument"또는 모듈 특정 대안)를 발생시키는 마지막 와일드 카드 패턴 ('_')을 추가하는 것입니다. –

    0

    웁스! 귀하의 질문을 읽지 마십시오. 후손을 위해 아래 내 답변을 남겨주세요.

    업데이트 답변 : hashtbl에서 체크를 수행하는 이유가 있습니까? 아니면 hashtbl에 구체적인 데이터 유형 (유형 값)을 가질 수없는 이유가 무엇입니까? 그것은 사물을 단순화합니다. 그러나 너희는 Array.get에 부울에 대한 검사를 이동하고 클로저를 사용할 수 있습니다

    | GVar s -> 
         begin 
          try 
           let (i,_) = Hashtbl.find variables s in 
            match (Array.get var_values i) with BOOL(v) -> (fun s -> v) 
            | _ -> raise (SemanticException (BoolExpected,s)) 
          with 
           Not_found -> raise (SemanticException (VarUndefined,s)) 
         end 
    

    가 또는 내가 당신의 코드를 단순화하기 위해 더 나을 것 같아요. 형식, 인덱스 및 값 배열 대신에 값을 Hashtbl로 이동하십시오. 아니면 그냥 Hashtbl에 인덱스를 저장하고 배열의 유형을 확인하십시오.아래

    오답은 :

    당신은 일치로하는 경우 다른 사람을 대체 할 수 있습니다. 또는 당신은 일치로하자를 대체 할 수

    는 경우/다른 대체 :

    | GVar s -> 
         begin 
          try 
           let (i,t) = Hashtbl.find variables s in 
            match t with Bool -> (fun s -> let BOOL v = Array.get var_values i in v) 
            | _ -> raise (SemanticException (BoolExpected,s)) 
          with 
           Not_found -> raise (SemanticException (VarUndefined,s)) 
         end 
    

    하자 대체 :

    | GVar s -> 
         begin 
          try 
           match (Hashtbl.find variables s) with (i, Bool) -> (fun s -> let BOOL v = Array.get var_values i in v) 
            | _ -> raise (SemanticException (BoolExpected,s)) 
          with 
           Not_found -> raise (SemanticException (VarUndefined,s)) 
         end 
    
    +0

    문제는 변수 유형 'Bool | 'var_values'가'value 배열'이기 때문에 i_th 요소가'BOOL v' 타입이되도록 강제하기 때문에''BOOL v = var_values ​​(i) 'variables' 해시 테이블을 확인했습니다 .. – Jack

    +0

    그래, 방금 이것을 깨닫고 내 대답을 업데이트했습니다. –

    3

    다형성 변이체, 좋은 대답이다.

    그러나 때로는 불가능한 경우가 있습니다. 그리고 나는 그것이 자연이 다른 숨길 수 -w p 플래그를 사용하는 것보다 훨씬 더

    (fun s -> match Array.get var_values i with 
          | BOOL v -> v 
          | _ -> assert false) 
    

    작성 찾아, 원하지 않는 비 철저한 패턴이 일치합니다.