2011-05-15 64 views
1

我已经定义了F#树和堆栈类型,堆栈上有一个弹出成员。流行音乐的结果我无法得到类型签名。这里是我的代码,直到我尝试使用弹出:返回中等复杂度的难度F#类型签名

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 

throws: stdin(22,24):错误FS0001:此表达式预计有 ('a *'b)*'c 但这里有类型 (Tree * int)Stack - >(Tree * int )*(Tree * int)堆栈

//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 

上面的尝试未注释的抛出: 标准输入(16,46):错误FS0001:预计这个表达式为具有类型 (树< 'B> * INT)*' C 但这里的类型是 “堆栈

回答

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作为实例成员,因为它更像是偷看。所以,你可能要实现它作为一个伴侣模块中的功能(或/和作为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