在F#中,如何更改记录中属性的属性(语法?)
假设我有这样一个记录:在F#中,如何更改记录中属性的属性(语法?),f#,F#,假设我有这样一个记录: type Page = { footersize: Size } 仅更改页脚大小高度的正确语法是什么 { page with footersize = ??? } 短暂性脑缺血发作 编辑#1:“大小”是框架元素的大小,即。, 在.Net世界中,大小是大小(宽度、高度),是一种结构,而不是记录。如下文所述, 这不起作用: {p with footersize = {p.footersize with Height = 96 * 0.5}} 错误:此表达式应具
type Page = { footersize: Size }
仅更改页脚大小高度的正确语法是什么
{ page with footersize = ??? }
短暂性脑缺血发作
编辑#1:“大小”是框架元素的大小,即。,
在.Net世界中,大小是大小(宽度、高度),是一种结构,而不是记录。如下文所述,
这不起作用:
{p with footersize = {p.footersize with Height = 96 * 0.5}}
错误:此表达式应具有类型“Size”,但此处为类型页。最直接的方法是复制并更新整个对象:
let page' =
{ page with
FooterSize = Size(page.FooterSize.Width, 100.)
}
如果你有更深的巢穴,它会变得更难
type Page = { FooterSize: Size }
type Document = { Title: string; Page: Page }
let document = { Title = "Fun and Profit"; Page = { FooterSize= Size(10., 10.) } }
要更新高度,现在必须执行以下操作:
let document' = { document with Page = { document.Page with FooterSize= Size(document.Page.FooterSize.Width, 100.) }}
那就从屏幕上消失了!有一个,允许您执行{documentwithpage.FooterSize.Height=100.}
,但这还有一点距离
镜头
当然,我们可以通过简单地使用compose right操作符获得值:
let (w, h) = (getPage >> getFooterSize >> getWH) document
但设置并不能构成。
但只要使用三个简单的运算符,我们就可以得到非常可读的内容:
let get (getter, _) = getter
let set (_, setter) = setter
let (>=>) (get_ab, set_ab) (get_bc, set_bc) =
get_ab >> get_bc,
fun a c -> set_ab a (set_bc (get_ab a) c)
因为我们的镜头只是一对吸气剂和设置剂:
let pageL = getPage, setPage
let footerL = getFooterSize, setFooterSize
let sizeL = getWH, setWH
就这样。那些是我们的镜片。现在,我们可以使用我们定义的fish操作符(=>
)合成这些镜头
let (footer_w, footer_h) = get (pageL >=> footerL >=> sizeL) document
let document' = set (pageL >=> footerL >=> sizeL) document (footer_w, 100.)
当然,你可以用更短的形式写一个镜头:
let pageL : Lens<Document, Page> =
(fun d -> d.Page), (fun d p -> { d with Page = p })
let pageL:Lens=
(fundd->d.Page),(fundp->{d with Page=p})
最直接的方法是复制并更新整个对象:
let page' =
{ page with
FooterSize = Size(page.FooterSize.Width, 100.)
}
如果你有更深的巢穴,它会变得更难
type Page = { FooterSize: Size }
type Document = { Title: string; Page: Page }
let document = { Title = "Fun and Profit"; Page = { FooterSize= Size(10., 10.) } }
要更新高度,现在必须执行以下操作:
let document' = { document with Page = { document.Page with FooterSize= Size(document.Page.FooterSize.Width, 100.) }}
那就从屏幕上消失了!有一个,允许您执行{documentwithpage.FooterSize.Height=100.}
,但这还有一点距离
镜头
当然,我们可以通过简单地使用compose right操作符获得值:
let (w, h) = (getPage >> getFooterSize >> getWH) document
但设置并不能构成。
但只要使用三个简单的运算符,我们就可以得到非常可读的内容:
let get (getter, _) = getter
let set (_, setter) = setter
let (>=>) (get_ab, set_ab) (get_bc, set_bc) =
get_ab >> get_bc,
fun a c -> set_ab a (set_bc (get_ab a) c)
因为我们的镜头只是一对吸气剂和设置剂:
let pageL = getPage, setPage
let footerL = getFooterSize, setFooterSize
let sizeL = getWH, setWH
就这样。那些是我们的镜片。现在,我们可以使用我们定义的fish操作符(=>
)合成这些镜头
let (footer_w, footer_h) = get (pageL >=> footerL >=> sizeL) document
let document' = set (pageL >=> footerL >=> sizeL) document (footer_w, 100.)
当然,你可以用更短的形式写一个镜头:
let pageL : Lens<Document, Page> =
(fun d -> d.Page), (fun d p -> { d with Page = p })
let pageL:Lens=
(fundd->d.Page),(fundp->{d with Page=p})
尺寸的定义是什么?假设尺寸也是一个记录;而Height
是一种int
,它是一种内置的编写{page with footersize={page.footersize with Height=10}}
的方式。如果您经常进行这种嵌套更新,还可以使用镜头抽象(例如,来自的镜头抽象)@Asti Size,如在.Net WPF中,is Size(Double,Double)初始化Size结构的新实例,并为其指定初始宽度和高度。@Mankarse--oops,不起作用。请参阅补充信息。谢谢。Size
的定义是什么?假设Size
也是一个记录;而Height
是一种int
,它是一种内置的编写{page with footersize={page.footersize with Height=10}}
的方式。如果您经常进行这种嵌套更新,还可以使用镜头抽象(例如,来自的镜头抽象)@Asti Size,如在.Net WPF中,is Size(Double,Double)初始化Size结构的新实例,并为其指定初始宽度和高度。@Mankarse--oops,不起作用。请参阅补充信息。谢谢。这是我见过的最好的镜片解释。谢谢,谢谢,艾伦。如果你来自C#背景,总会有一段震惊期。但这很快就会过去。坚持下去!这是我所见过的镜头的最好解释。谢谢,谢谢,艾伦。如果你来自C#背景,总会有一段震惊期。但这很快就会过去。坚持下去!