In C#, I am using the following function which I want to move into F#:
public virtual void BringToTop(LayersEnum _TopMostLayer)
{
if (LayerName == _TopMostLayer)
{
ZIndex = 10;
Visibility = Visibility.Visible;
}
else
{
ZIndex = DefaultZIndex;
Visibility = Visibility.Hidden;
}
}
Assuming I have the following F# definitions, how is this implemented in 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
}
My very FAILED attempt is:
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},
Error: The record label "Visibility" is not defined
Thank you for any help.
#Addendum:
Ultimately, I would like to implement the interface on the different record types of WritingLayer.Model, ImageLayer.Model, and ChartLayer.Model to be used as:
{m with WritingLayer = BringToTop rb m.WritingLayer;
ImageLayer = BringToTop rb m.ImageLayer;
ChartLayer = rb m.ChartLayer}
Thank you for your consideration.
This code won't work as-is:
let BringToTop rb (layer:ILayer) =
if rb.ToString() = layer.Name then
{ layer with Visibility =true }
else
{ layer with Visibility = false }
This is because F# doesn't implicitly downcast to a type that implements the interface.
First potential solution:
Switch from being passed an ILayer
to just being passed a Model
directly. Then your code will work.
Second potential solution:
I'm assuming that since you have an interface, you want to pass that around as the data type rather than the model type itself. If that is the case, then I'd recommend using an Object Expression to update the data like so:
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
Third potential solution
If you're fine with downcasting , you can shadow your first layer
definition like so:
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 }
But usually whenever a downcast is involved that's a code smell, so I'd really recommend constructing a new instance of the interface instead.
I never could do this the way I wanted to--by using the ILayer interface to update and return the record type it was associated with. I would be most interested in a better way to do this.
What I did end up doing was simply to define three specific functions, one for each type as:
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}
with usage as:
{ m with DocumentLayer = documentRadioButton;
WritingLayer = BringToTopWritingLayer documentRadioButton m.WritingLayer;
ImageLayer = BringToTopImageLayer documentRadioButton m.ImageLayer;
ChartLayer = BringToTopChartLayer documentRadioButton m.ChartLayer}
This seems highly redundant, but it does seem to compile correctly.
A better answer would be most appreciated.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.