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


F# how to pass interface to a function?

我的动作数据如下:

1
2
3
4
5
6
7
8
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传递给函数,该函数仅在意布尔" show "成员,但无法弄清楚如何传递/广播它:

1
2
3
4
5
6
7
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

但是如何调用此函数?

1
let setShowFn = setShowItem (data :> IHasShow) not

错误:

1
2
3
4
Type constraint mismatch. The type
    'ShowHideNotCompletedData'    
is not compatible with type
    'IHasShow'

尝试

1
let setShowFn = setShowItem data not

错误:

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

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

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

最简单的解决方案是不传递数据,而仅传递布尔值:

1
2
3
4
5
6
7
8
9
10
11
12
13
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}

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


我必须承认:我不喜欢F#中的接口-并不是一般而言,但从语法上我认为它们完全是一场灾难。
因此,我经常不使用带有类型约束的内联函数。
Achtung:使用这种代码可能会杀死十几只小狗或sort

首先要摆脱您的界面及其实现(无论如何您已经忘记了它;-))

1
2
3
4
5
type ShowHideNotCompletedData       = {show:bool}
type ShowHideCompletedData          = {show:bool}
type ActionData =
    | ShowHideNotCompleted of ShowHideNotCompletedData
    | ShowHideCompleted of ShowHideCompletedData

然后编写看起来非常疯狂的功能

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

并应用

1
2
3
4
let setShowItem data =
    match data with
    | ShowHideNotCompleted x -> show x
    | ShowHideCompleted x -> show x


在当前解决方案中,两个类型ShowHideNotCompletedDataShowHideCompletedData是记录。它们具有接口的所有字段,但未明确实现它们。解决方案是使接口显式:

1
2
3
4
5
6
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发布了一个没有界面的答案。就模块性和可测试性而言,您自己的建议只是将布尔值传递给函数似乎更好。