2011-05-15 23 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