模式鉴别器不匹配

Vin*_*cio 2 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''
Run Code Online (Sandbox Code Playgroud)

Mar*_*ann 5

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

let binaryMathFn fn stack =

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

    let result = fn item1 item2

    push result stack''
Run Code Online (Sandbox Code Playgroud)

你的定义Stack是一个被歧视的联盟,有一个叫做的联合案例StackContents.当您将函数参数声明为时(StackContents stack),您使用的是速记符号,表示:

输入属于类型Stack,但会立即将该输入与单个StackContents联合情况匹配,float list从输入中有效地解压缩,并将其分配float list给符号stack.

如果您像我上面建议的那样,将参数声明更改为简单stack,F#编译器可以自动推断它stack是一个Stack值,因为该函数使用了pop具有此函数签名的函数:

Stack -> float * Stack
Run Code Online (Sandbox Code Playgroud)

这被读作采用一个函数Stack作为输入,并返回的元组floatStack作为输出.由于binaryMathFn电话popstack,编译器可以推断stack必须是一个Stack值.

  • 事实上,这是来自C#的新F#ers的一个主要问题 - 语法看起来非常像C#中的普通参数定义,他们看不出差异 (2认同)