문제

이 매우 간단한 SML 기능의 테일 리퍼 시브 버전을 만들려고했습니다.

fun suffixes [] = [[]]
  | suffixes (x::xs) = (x::xs) :: suffixes xs;

이 과정에서 나는 매개 변수에 유형 주석을 사용하고있었습니다. 다음 코드는 이것을 보여주고 유형 오류 (아래 주어진)를 유발하는 반면, 유형 주석을 간단히 제거하면 SML은 문제없이 그것을 받아 들여 전체 기능에 위의 단순한 기능과 동일한 시그니처를 제공합니다.

fun suffixes_tail xs =
    let
        fun suffixes_helper [] acc = []::acc
          | suffixes_helper (x::xs:'a list) (acc:'b list) =
                suffixes_helper xs ((x::xs)::acc)
    in
        suffixes_helper xs []
    end;

오류:

$ sml typeerror.sml 
Standard ML of New Jersey v110.71 [built: Thu Sep 17 16:48:42 2009]
[opening typeerror.sml]
val suffixes = fn : 'a list -> 'a list list
typeerror.sml:17.81-17.93 Error: operator and operand don't agree [UBOUND match]
  operator domain: 'a list * 'a list list
  operand:         'a list * 'b list
  in expression:
    (x :: xs) :: acc
typeerror.sml:16.13-17.94 Error: types of rules don't agree [UBOUND match]
  earlier rule(s): 'a list * 'Z list list -> 'Z list list
  this rule: 'a list * 'b list -> 'Y
  in rule:
    (x :: xs : 'a list,acc : 'b list) =>
      (suffixes_helper xs) ((x :: xs) :: acc)
/usr/local/smlnj-110.71/bin/sml: Fatal error -- Uncaught exception Error with 0
 raised at ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27

주어진 두 가지 오류가 있습니다. 후자는 여기서 덜 중요해 보인다. 첫 번째는 내가 이해하지 못하는 것입니다. 첫 번째 매개 변수가 유형이라고 말하기 위해 주석을 달았습니다. 'a:list 그리고 두 번째 매개 변수는 유형입니다 'b:list. 내가 이해할 수있는 일반적인 통일의 최상위로 구축 된 Hindley-Milner Type 유험 알고리즘은 통일 할 수 없어야합니다. 'b:list ~와 함께 'a:list list, 대체를 사용합니다 'b ---> 'a list?

편집 : 답변은 유형 주석에 의해 주어진 것보다 어떤 의미에서 유추 알고리즘을 허용하지 않는 유형의 추론 알고리즘과 관련이있을 수 있음을 시사합니다. 그러한 규칙은 매개 변수와 전체 기능에 대한 주석에만 적용될 것이라고 생각합니다. 이것이 올바른지 모르겠습니다. 어쨌든, 나는 유형 주석을 기능 본문으로 옮기려고했는데 같은 종류의 오류가 발생합니다.

fun suffixes_helper [] acc = []::acc
    | suffixes_helper (x::xs) acc =
          suffixes_helper (xs:'a list) (((x::xs)::acc):'b list);

오류는 이제 다음과 같습니다.

typeerror.sml:5.67-5.89 Error: expression doesn't match constraint [UBOUND match]
  expression: 'a list list
  constraint: 'b list
  in expression:
    (x :: xs) :: acc: 'b list
도움이 되었습니까?

해결책

SML은 확실하지 않지만 또 다른 기능 언어 인 F#은 이런 종류의 상황에서 경고를합니다. 오류를 제공하는 것은 약간 가혹할 수 있지만 의미가 있습니다. 프로그래머가 추가 유형 변수 'B를 소개하고'B가 'A 목록이어야하는 경우, 기능이 프로그래머가 의도 한 것만 큼 일반적인 것이 아닐 수도 있습니다. 보고 할 가치가 있습니다.

다른 팁

이것은 작동합니다 :

fun suffixes_tail xs =
    let
        fun suffixes_helper [] acc = []::acc
          | suffixes_helper (x::xs:'a list) (acc:'a list list) =
                suffixes_helper xs ((x::xs)::acc)
    in
        suffixes_helper xs []
    end

Joh와 Newacct가 말했듯이 'b list 너무 느슨합니다. 명시 적 유형 주석을 줄 때

fun suffixes_helper (_ : 'a list) (_ : 'b list) = ...

암시 적으로 정량화됩니다

fun suffixes_helper (_ : (All 'a).'a list) (_ : (All 'b).'b list) = ...

그리고 분명히 'b = 'a list 사실이 될 수 없습니다 (All a') 그리고 (All b') 동시에.

명시 적 유형 주석이 없으면 유형을 통일하는 것이 올바른 일을 할 수 있습니다. 그리고 실제로, SML의 유형 시스템은 (내가 아는 한) 결코 없어서는 안되는 한, 명시 적 유형 주석이 필요하지 않을 정도로 간단합니다. 왜 여기에 넣고 싶습니까?

다음과 같은 유형 변수를 사용할 때 'a 그리고 'b, 그것은 그것을 의미합니다 'a 그리고 'b 설정할 수 있습니다 아무것, 독립적으로. 예를 들어, 내가 결정하면 작동해야합니다. 'b ~였다 int 그리고 'a ~였다 float; 그러나 분명히 그것은이 경우에 유효하지 않습니다. 'b 해야합니다 'a list.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top