我有一个标记的联合类型,包含一些记录数据,如
type Comment = New Content | Edited Content | Flagged Content
type alias Content = {id: Int, text: String}
Comment
类型声明状态。
当使用模式匹配例如按id过滤时,我必须写
filter Int -> Comment -> Bool
filter id comment =
case comment of
New content -> content.id == id
Edited content -> content.id == id
Flagged content -> content.id = id
这是有效的,但我必须为每个案例复制相同的逻辑,而不是我喜欢它简单
filter id comment =
case comment of
_ content -> content.id == id
使用过滤等功能这是简单的一行重复,但在基于状态呈现内容时,HTML生成逻辑的重复更严重。
我知道在Elm中,union类型可以携带不同的“有效负载”,并且编译器不喜欢通用版本,但是在这种情况下有一些方法告诉编译器所有这些情况都处理相同的记录类型?
或者这是无效使用联合类型的情况,模型的结构应该不同?也许国家是记录类型的一部分。
或者这是无效使用联合类型的情况,模型的结构应该不同?
如果所有三个变体都将包含相同的数据,那么是。
我将在顶部使用记录并为Comment的“Status”创建一个标记的联合。
type alias Comment =
{ id : Int
, text : String
, status : Status
}
type Status
= New
| Edited
| Flagged
这将使访问id
和text
的评论变得容易。如果你做case comment.status of ...
,你仍然会得到详尽的模式匹配的好处。
您可以将获取内容部分分解出来
type Comment = New Content | Edited Content | Flagged Content
type alias Content = {id: Int, text: String}
filter : Int -> Comment -> Bool
filter id comment =
let content = commentContent comment
in content.id == id
commentContent : Comment -> Content
commentContent comment =
case comment of
New content -> content
Edited content -> content
Flagged content -> content
您可以进一步抽象,例如,如果要添加文本过滤器
filter : Int -> Comment -> Bool
filter id comment =
doFilter (\c -> c.id == id) comment
filterText : String -> Comment -> Bool
filterText text comment =
doFilter (\c -> c.text == text) comment
doFilter : (Content -> Bool) -> Comment -> Bool
doFilter f comment =
let content = commentContent comment
in f content
最后,添加一些功能风格......
doFilter : (Content -> Bool) -> Comment -> Bool
doFilter f = f << commentContent