模式鉴别器不匹配

时间:2014-07-04 06:37:59

标签: f#

F#的新手,想知道为什么我在定义binaryMathFn时遇到编译时错误。

我还会就改变这个问题的标题提出建议。它不是最具描述性的:)

type Stack = StackContents of float list

let push item (StackContents stack) =
    match stack with
    | [] -> StackContents [item]
    | _ ->  StackContents (item::stack)

let pop (StackContents stack) =
    match stack with
    | [] -> failwith "Stack is empty, nothing to pop!"
    | h::t -> (h, StackContents t)    

let binaryMathFn fn (StackContents stack) = // Expression type is expected to be of type Stack?

    let item1, stack' = pop stack
    let item2, stack'' = pop stack'

    let result = fn item1 item2

    push result stack''

2 个答案:

答案 0 :(得分:5)

答案在于类型,但在我解释什么是错的之前,这是使binaryMathFn函数编译的一种方法:

let binaryMathFn fn stack =

    let item1, stack' = pop stack
    let item2, stack'' = pop stack'

    let result = fn item1 item2

    push result stack''

您对Stack的定义是一个歧视联盟,其中包含一个名为StackContents的联合案例。当您将函数参数声明为(StackContents stack)时,您使用的是速记符号:

输入属于Stack类型,但会立即将该输入与单StackContents联合案例进行匹配,从输入中有效解包float list,并指定float list }到符号stack

如果您像我上面建议的那样将参数声明更改为stack,则F#编译器可以自动推断stackStack值,因为该函数使用{ {1}}函数,具有此函数签名:

pop

读作一个以Stack -> float * Stack 为输入的函数,并返回Stackfloat元组作为输出。自{{1使用Stack调用binaryMathFn,编译器可以推断pop必须是stack值。

答案 1 :(得分:3)

所以问题是:

let binaryMathFn fn (StackContents stack)

应该是

let binaryMathFn fn (stack)

正在发生的是您的定义是提取数据。通常,使用您在函数定义中使用的这种模式匹配是单一的。