我目前正在用 F# 制作一个具有寓言 elmish 架构的应用程序,其中记录类型如下(减少以节省空间,但希望您能明白)。
type NewOriginMerdEntry =
| AddOriginMerdID of string
| AddMerdNumber of int
| AddAverageWeight of float
| AddPD of int
type NewTreatmentEntry =
| AddTreatmentID of string
type NewDestMerdEntry =
| AddDestMerdID of string
....etc
现在我已经将它们编译成一个有区别的联合类型,比如这样
type NewEntry =
| NewOriginMerdEntry of NewOriginMerdEntry
| NewTreatmentEntry of NewTreatmentEntry
| NewDestMerdEntry of NewDestMerdEntry
...etc
最后主要消息类型如下所示:
type Msg = {
NewEntry of NewEntry
}
这很干净,但是在视图函数中,我需要为每种类型创建一个新函数来表示视图以及在文本输入更改时需要调度的特定消息。
这是这样的:
let originMerdView (dispatch : Msg -> unit) (model : Model) =
let dispatch' = NewOriginMerdEntry >> NewEntry >> dispatch
let form = match model.form with
| OriginMerd o -> o
| _ -> None
R.scrollView[
P.ViewProperties.Style [
P.FlexStyle.FlexGrow 1.
P.BackgroundColor "#000000"
]
][
//these functions are simply calls to various input text boxes
inputText "ID" AddOriginMerdID dispatch'
numinputText "MerdNumber" AddMerdNumber dispatch'
floatinputText "average Weight" AddAverageWeight dispatch'
numinputText "PD" AddPD dispatch'
button "save" form SaveOriginMerd (SaveEntry >> dispatch)
]
let inputText label msg dispatch =
R.textInput[
P.TextInput.OnChangeText ( msg >> dispatch )
]
所以第一个问题是,是否有可能以某种方式概括这一点,因为主视图将根据模型状态决定运行哪些函数。它工作正常,但代码重复量相当痛苦。
此外,每个新条目都将发送到此函数:
let handleNewEntry (model : Model) (entry : NewEntry) =
match entry with
| NewOriginMerdEntry e -> handleNewOriginMerdEntry model e
... etc
let handleNewOriginMerdEntry (model : Model) (entry : NewOriginMerdEntry) =
let form =
match model.form with
| OriginMerd o -> match o with
| Some f -> f
| None -> OriginMerd.New
| _ -> failwithf "expected origin type got something else handleNewOriginMerd"
let entry =
match entry with
| AddOriginMerdID i -> {form with originMerdID = i}
| AddMerdNumber n -> {form with merdNumber = n}
| AddPD p -> {form with pD = p}
| AddAverageWeight w -> {form with averageWeight = w}
{model with form = OriginMerd (Some entry)}, Cmd.none
除了明显不同的记录外,所有特定的句柄新条目功能完全相同。这功能很好,但代码重用再次非常痛苦。有没有更优雅的方法可以用更少的代码重复实现相同的结果?