2013-03-01 5 views
0
type Name = string; 
datatype Expr = Const of int 
    | Var of Name 
    | Neg of Expr 
    | Plus of Expr * Expr 
    | Mult of Expr * Expr 
    | App of Fun * Expr 
    and Fun = Def of Name * Expr 

(* substitute every x in expression z with expression y *) 

fun substitute (Name x, Expr y, Expr z) = if x = z then y else z; 

x 및 z의 문자열 값을 비교하고 동일한 y 값을 반환하고, 그렇지 않으면 z를 반환하지만이 오류가 계속 발생합니까?ML의 다른 데이터 유형 비교

e.sml:13.33-13.39 Error: non-constructor applied to argument in pattern: Expr 
e.sml:13.25-13.31 Error: non-constructor applied to argument in pattern: Expr 
e.sml:13.17-13.23 Error: non-constructor applied to argument in pattern: Name 
e.sml:13.50 Error: unbound variable or constructor: z 
e.sml:13.46 Error: unbound variable or constructor: x 
e.sml:13.57 Error: unbound variable or constructor: y 
e.sml:13.64 Error: unbound variable or constructor: z 

uncaught exception Error 
    raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27 
     ../compiler/TopLevel/interact/evalloop.sml:44.55 
     ../compiler/TopLevel/interact/evalloop.sml:296.17-296.20 

답변

3

의미의 지옥을 많이하지 않습니다 substitute 귀하의 정의). 먼저 유형과 패턴 매칭을 잘못 사용하고 두 번째로 루트 표현식뿐만 아니라 재귀 적으로 대체해야합니다.

fun substitute(x, e, Const n)  = Const n 
    | substitute(x, e, Var y)  = if x = y then e else Var y 
    | substiture(x, e, Neg e')  = Neg(substitute(x, e, e')) 
    | substitute(x, e, Plus(e1, e2)) = Plus(substitute(x, e, e1), substitute(x, e, e2)) 
    | ... 

당신이 남아있는 경우에 입력 할 수 있어야한다 : 여기

는 작업 버전의 스케치입니다. App 케이스는 실수로 함수를 캡처하는 것을 피하기 위해 약간의주의가 필요합니다. 즉, x이 매개 변수 변수와 같을 때 본문을 대체하지 않아야합니다. 이 유형의 주석을 제공에 촉각을 곤두 세우고있다 경우

,이 기능을 가장 잘 경우에 기록됩니다

경우 단지 문법 설탕, 이는 이전에 해당의
fun substitute(x : Name, e : Expr, z : Expr) = 
    case z of 
     Const n => z 
    | Var y => if x = y then e else z 
    | Neg e' => Neg(substitute(x, e, e')) 
    ... 

.

1

당신은 함수 매개 변수에 대한 구문이 typename variablename이라고 생각하는 것 같다. 그렇지 않습니다. 구문은 pattern : typename 또는 단지 pattern입니다. 가장 간단한 형식의 패턴은 단순히 변수 이름입니다.

Name x과 같은 것을 작성하면 Name이 일부 데이터 유형의 생성자이고 해당 생성자에 대한 첫 번째 인수 (해당 데이터 유형의 값이어야 함)와 패턴을 일치 시키려고한다는 것을 의미합니다. 그것은 당신이 원하는 것이 아닙니다.

fun substitute (x: Name, y: Expr, z: Expr) = ... 

: 당신이 매개 변수의 유형을 주문하려면,

fun substitute (x, y, z) = ... 

을 또는 :

인수 x, yz를받는 함수를 정의하려면, 당신은 단지 작성해야 추신 : 귀하의 함수 본문에서는 x = z을 작성하지만, 작동하지 않습니다. xz은 다른 유형의 값입니다. 서로에게.

+0

그렇다면 이름을 Var과 어떻게 비교할 수 있습니까? 둘 다 문자열이기 때문에 어떻게해야합니까? – Jae

+2

@Jay' "hello"'는 문자열입니다. 'Var "hello"는 문자열이 아니며'Expr' 유형의 값입니다. string 형의 값 (또는'Name', 같은 것)과'Expr' 형의 또 다른 값을 가지고 있고'Expr'이 주어진 이름을 가진'Var'인지를 검사하기를 원한다면 a) 'Expr'이 실제로 'Var'인지 확인하고 b) 문자열을 'Var'에서 가져와 다른 문자열과 비교할 수있는 패턴 매칭을 사용해야합니다. 그것이 당신에게 이해가되지 않으면 ML에서 패턴 매칭이 어떻게 작동 하는지를 읽어야합니다. – sepp2k