如何使用 F# 中的接口更新和 return 记录
How to update and return a record using an interface in F#
在 C# 中,我正在使用以下我想移至 F# 中的函数:
public virtual void BringToTop(LayersEnum _TopMostLayer)
{
if (LayerName == _TopMostLayer)
{
ZIndex = 10;
Visibility = Visibility.Visible;
}
else
{
ZIndex = DefaultZIndex;
Visibility = Visibility.Hidden;
}
}
假设我有以下 F# 定义,这在 F# 中是如何实现的:
type DocumentRadioButtons = ChartLayer | WritingLayer | ImageLayer | TranscriptionLayer | PublisherLayer
module WritingLayer=
type Model =
{ Name: string
Visibility: bool
DefaultZIndex: int
ZIndex: int
}
interface ILayer with
member this.Name with get() = this.Name
member this.Visibility with get() = this.Visibility
member this.DefaultZIndex with get() = this.DefaultZIndex
member this.ZIndex with get() = this.ZIndex
type ProgressNoteWin = {
ConfirmState: ConfirmState option
Encounter: view_doctor_encounter
LastName: string
DocumentLayer: DocumentRadioButtons
WritingLayer: WritingLayer.Model
ImageLayer: ImageLayer.Model
ChartLayer: ChartLayer.Model
}
我非常失败的尝试是:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then {layer with Visibility =true} else {layer with Visibility = false }
{ m with WritingLayer = BringToTop documentRadioButton m.WritingLayer},
错误:未定义记录标签“可见性”
感谢您的帮助。
#附录:
最终,我想在 WritingLayer.Model、ImageLayer.Model 和 ChartLayer.Model 的不同记录类型上实现接口,用作:
{m with WritingLayer = BringToTop rb m.WritingLayer;
ImageLayer = BringToTop rb m.ImageLayer;
ChartLayer = rb m.ChartLayer}
感谢您的考虑。
此代码无法按原样运行:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
{ layer with Visibility =true }
else
{ layer with Visibility = false }
这是因为 F# 不会隐式向下转换为实现该接口的类型。
第一个可能的解决方案:
从传递 ILayer
切换到直接传递 Model
。然后你的代码就可以工作了。
第二个可能的解决方案:
我假设既然您有一个接口,您希望将其作为数据类型而不是模型类型本身传递。如果是这种情况,那么我建议使用对象表达式来更新数据,如下所示:
let mkILayer visible (layer: ILayer) =
{ new ILayer with
member this.Name = layer.Name
member this.Visibility = visible
member this.DefaultZIndex = layer.DefaultZIndex
member this.ZIndex = layer.ZIndex }
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
mkILayer true layer
else
mkILayer false layer
第三种可能的解决方案
如果您对 downcasting 没意见,您可以隐藏您的第一个 layer
定义,如下所示:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
let layer = layer :?> Model
{ layer with Visibility =true }
else
let layer = layer :?> Model
{ layer with Visibility = false }
但通常每当涉及到一个向下转型时,这就是代码味道,所以我真的建议改为构造一个新的接口实例。
我永远无法按照我想要的方式执行此操作——通过使用 ILayer 界面更新和 return 它关联的记录类型。我最感兴趣的是更好的方法。
我最终所做的只是简单地定义了三个特定的函数,每个函数对应一种类型:
let BringToTopWritingLayer rb layer:WritingLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
let BringToTopImageLayer rb layer:ImageLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
let BringToTopChartLayer rb layer:ChartLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
用法为:
{ m with DocumentLayer = documentRadioButton;
WritingLayer = BringToTopWritingLayer documentRadioButton m.WritingLayer;
ImageLayer = BringToTopImageLayer documentRadioButton m.ImageLayer;
ChartLayer = BringToTopChartLayer documentRadioButton m.ChartLayer}
这似乎非常多余,但似乎编译正确。
如有更好的回答,将不胜感激。
在 C# 中,我正在使用以下我想移至 F# 中的函数:
public virtual void BringToTop(LayersEnum _TopMostLayer)
{
if (LayerName == _TopMostLayer)
{
ZIndex = 10;
Visibility = Visibility.Visible;
}
else
{
ZIndex = DefaultZIndex;
Visibility = Visibility.Hidden;
}
}
假设我有以下 F# 定义,这在 F# 中是如何实现的:
type DocumentRadioButtons = ChartLayer | WritingLayer | ImageLayer | TranscriptionLayer | PublisherLayer
module WritingLayer=
type Model =
{ Name: string
Visibility: bool
DefaultZIndex: int
ZIndex: int
}
interface ILayer with
member this.Name with get() = this.Name
member this.Visibility with get() = this.Visibility
member this.DefaultZIndex with get() = this.DefaultZIndex
member this.ZIndex with get() = this.ZIndex
type ProgressNoteWin = {
ConfirmState: ConfirmState option
Encounter: view_doctor_encounter
LastName: string
DocumentLayer: DocumentRadioButtons
WritingLayer: WritingLayer.Model
ImageLayer: ImageLayer.Model
ChartLayer: ChartLayer.Model
}
我非常失败的尝试是:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then {layer with Visibility =true} else {layer with Visibility = false }
{ m with WritingLayer = BringToTop documentRadioButton m.WritingLayer},
错误:未定义记录标签“可见性”
感谢您的帮助。
#附录:
最终,我想在 WritingLayer.Model、ImageLayer.Model 和 ChartLayer.Model 的不同记录类型上实现接口,用作:
{m with WritingLayer = BringToTop rb m.WritingLayer;
ImageLayer = BringToTop rb m.ImageLayer;
ChartLayer = rb m.ChartLayer}
感谢您的考虑。
此代码无法按原样运行:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
{ layer with Visibility =true }
else
{ layer with Visibility = false }
这是因为 F# 不会隐式向下转换为实现该接口的类型。
第一个可能的解决方案:
从传递 ILayer
切换到直接传递 Model
。然后你的代码就可以工作了。
第二个可能的解决方案:
我假设既然您有一个接口,您希望将其作为数据类型而不是模型类型本身传递。如果是这种情况,那么我建议使用对象表达式来更新数据,如下所示:
let mkILayer visible (layer: ILayer) =
{ new ILayer with
member this.Name = layer.Name
member this.Visibility = visible
member this.DefaultZIndex = layer.DefaultZIndex
member this.ZIndex = layer.ZIndex }
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
mkILayer true layer
else
mkILayer false layer
第三种可能的解决方案
如果您对 downcasting 没意见,您可以隐藏您的第一个 layer
定义,如下所示:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
let layer = layer :?> Model
{ layer with Visibility =true }
else
let layer = layer :?> Model
{ layer with Visibility = false }
但通常每当涉及到一个向下转型时,这就是代码味道,所以我真的建议改为构造一个新的接口实例。
我永远无法按照我想要的方式执行此操作——通过使用 ILayer 界面更新和 return 它关联的记录类型。我最感兴趣的是更好的方法。
我最终所做的只是简单地定义了三个特定的函数,每个函数对应一种类型:
let BringToTopWritingLayer rb layer:WritingLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
let BringToTopImageLayer rb layer:ImageLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
let BringToTopChartLayer rb layer:ChartLayer.Model =
if rb.ToString() = (layer :>ILayer).Name
then
{layer with Visibility = true}
else
{layer with Visibility = false}
用法为:
{ m with DocumentLayer = documentRadioButton;
WritingLayer = BringToTopWritingLayer documentRadioButton m.WritingLayer;
ImageLayer = BringToTopImageLayer documentRadioButton m.ImageLayer;
ChartLayer = BringToTopChartLayer documentRadioButton m.ChartLayer}
这似乎非常多余,但似乎编译正确。
如有更好的回答,将不胜感激。