F#如何将接口传递给函数?

时间:2017-02-16 13:52:39

标签: 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传递给一个函数,该函数只关心一个布尔值&#34; show&#34;成员,但无法弄清楚如何传递/施放它:

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'

除了使用ShowHideNotCompletedData和ShowHideCompleted复制粘贴setShowItem之外,还有其他方法吗?

如果有帮助;完整的源代码在这里:https://github.com/amsterdamharu/riot_redux_fable

最简单的解决方案是不传递数据,而只传递bool:

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}

我仍然想知道如何定义泛型类型并传递它。

2 个答案:

答案 0 :(得分: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发布了一个没有界面的答案。在模块化和可测试性方面,你自己建议将bool传递给函数似乎更好。

答案 1 :(得分: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