难以返回中等复杂的F#型签名

时间:2011-05-15 20:34:14

标签: f#

我已经定义了F#Tree和Stack类型,在堆栈上有一个pop成员。我无法在pop的结果上获得类型签名。这是我的代码,直到我尝试使用pop:

type Tree<'a> =
    | Tree of 'a * 'a Tree * Tree<'a>
    | Node of 'a 
    | None

type 'a Stack =
    | EmptyStack 
    | Stack of 'a * 'a Stack 
    member x.pop = function
        | EmptyStack -> failwith "Empty stack"
        | Stack(hd, tl) -> (hd:'a), (tl:Stack<_>)

let myTree = Tree("A", Tree("B", Node("D"), None), Tree("C", Tree("E", None, Node("G")),  Tree("F", Node("H"), Node("J"))))

let myStack = Stack((myTree, 1), Stack.EmptyStack)

现在我尝试了各种方法来返回弹出窗口,每个方法都会在签名中引发不同类型的错误:

let (tree, level), z = myStack.pop

抛出: stdin(22,24):错误FS0001:此表达式应该具有类型     ('a *'b)*'c 但这里有类型     (Tree * int)Stack - &gt; (Tree * int)*(Tree * int)Stack

//let (tree:Tree<_>, level:int), z:Stack<Tree<_>*int> = myStack.pop
let (tree:Tree<_>, level:int), z:Stack<'a> = myStack.pop
//let (tree:Tree<'a>, level:int), _ = myStack.pop
//let (tree:Tree<string>, level:int), z:Stack<Tree<string>*int> = myStack.pop

以上未注释的尝试抛出: stdin(16,46):错误FS0001:该表达式应该具有类型     (树&lt;'b&gt; * int)*'c 但这里有类型     '堆栈

1 个答案:

答案 0 :(得分:4)

问题是pop这里是一个带有一个参数的实例方法(由于function),但是你希望它是一个带零参数的实例方法(即单位),比如

type 'a Stack =
    | EmptyStack 
    | Stack of 'a * 'a Stack 
    member x.pop() =
        match x with
        | EmptyStack -> failwith "Empty stack"
        | Stack(hd, tl) -> (hd:'a), (tl:Stack<_>)

然后将其称为

let (tree,level), z = myStack.pop()

<强> [编辑]

但实际上,由于Stack在这里是不可变的,因此实现pop作为实例成员并没有意义,因为那时它真的更像是peek。因此,您可能希望将其实现为协同模块中的函数(或/和Stack的静态成员,以便与其他.NET语言兼容):

type 'a Stack = \\'
    | EmptyStack 
    | Stack of 'a * 'a Stack 

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Stack =
    let pop = function
        | EmptyStack -> failwith "Empty stack"
        | Stack(hd, tl) -> (hd:'a), (tl:Stack<_>)

并将其称为

let (tree, level), z = Stack.pop myStack