2017-02-16 70 views
4

我有行動的數據,看起來像:F#如何將接口傳遞給函數?

type IHasShow = 
    abstract member show:bool 
type ShowHideNotCompletedData  = {show:bool} 
type ShowHideCompletedData   = {show:bool} 
[<Pojo>] 
type ActionData = 
    | ShowHideNotCompleted of ShowHideNotCompletedData 
    | ShowHideCompleted of ShowHideCompletedData 

後來我試圖ShowHideNotCompletedData或ShowHideCompletedData傳遞給一個函數,該函數只關心一個布爾「秀」的成員,但無法弄清楚如何傳遞/施放它:

let setShowItem (data:IHasShow) negate item = 
    if data.show && (negate item.completed) then 
    { item with show = true} 
    else if (negate item.completed) then 
    { item with show = false} 
    else 
    item 

但是如何調用這個函數?

let setShowFn = setShowItem (data :> IHasShow) not 

錯誤:

Type constraint mismatch. The type 
    'ShowHideNotCompletedData'  
is not compatible with type 
    'IHasShow' 

試圖

let setShowFn = setShowItem data not 

錯誤:

The type 'ShowHideNotCompletedData' is not compatible with the type 'IHasShow' 

有沒有一種方法比複製粘貼setShowItem這等採取ShowHideNotCompletedData和ShowHideCompleted ?

如果有幫助;完整的源代碼是在這裏:https://github.com/amsterdamharu/riot_redux_fable

最簡單的解決方案是無法通過數據,但只有布爾:

let setShowItem show negate item = 
    if (negate item.completed) then//simplified if statement 
    { item with show = show} 
    else 
    item 
//... 

| ShowHideCompleted data -> 
    let setShowFn = setShowItem data.show id 
    { state with 
     showCompleted = data.show 
     items = state.items 
     |> Array.map setShowFn} 

我仍然不知道如何定義泛型類型和傳遞。

回答

3

在您當前的解決方案中,您的兩種類型ShowHideNotCompletedDataShowHideCompletedData是記錄。它們具有界面的所有字段,但不明確地實現它們。解決方案是使界面明確:

type ShowHideNotCompletedData(show) = 
    interface IHasShow with 
     member this.show = show 
type ShowHideCompletedData(show) = 
    interface IHasShow with 
     member this.show = show 

實例化爲ShowHideNotCompletedData true。對於替代解決方案,您可能想查閱一些有關鴨子打字的SO問題,例如this

說了這麼多:我有一個預感,您的數據類型定義有點太複雜。 @robkuz發佈了一個沒有界面的答案。在模塊化和可測試性方面,你自己的建議只是將一個布爾函數傳遞給函數。

3

我必須承認:我不喜歡F#中的接口 - 一般來說不是,但我認爲它們在語法上是徹底的毀滅。 所以我經常使用帶有類型約束的內聯函數。
ACHTUNG:使用這種代碼可能會殺了十幾小狗或排序

第一件事擺脫你的接口和它的實現(你已經忘了,反正;-))的

type ShowHideNotCompletedData  = {show:bool} 
type ShowHideCompletedData   = {show:bool} 
type ActionData = 
    | ShowHideNotCompleted of ShowHideNotCompletedData 
    | ShowHideCompleted of ShowHideCompletedData 

然後寫一個真正瘋狂的尋找功能

let inline show< ^T when ^T : (member show : bool)> (x:^T) = 
     (^T : (member show : bool)(x)) 

,並將其應用

let setShowItem data = 
    match data with 
    | ShowHideNotCompleted x -> show x 
    | ShowHideCompleted x -> show x 
+2

我和你在一起討厭界面。你的解決方案比接口更習慣。我不確定這是否是解決手頭問題的最佳解決方案,但數據類型似乎過於複雜,但OP沒有提供多少上下文。 –

+0

或'let inline show x =(^ T:(member show:bool)(x))'type inference FTW :-) – CaringDev