如何从自定义类型的多个变体中提取值?

How do you extract the value from multiple variants of a custom type?

我有这样的类型,

type Post 
    = Blog String String
    | Announcement String String

还有一个函数,

upcaseTitle : Post -> Post
upcaseTitle post =
    case post of
        Blog title body ->
            { post | title = String.toUpper title }
        Announcement title body ->
            { post | title = String.toUpper title }

我想写这样的代码,

upcaseTitle : Post -> Post
upcaseTitle post =
    case post of
        Post title body ->
            { post | title = String.toUpper title }

我想在我的 case 语句中添加一个匹配所有 Post 类型的子句,并提取常见的 Stringtitle,因为它是所有共享的我的联合类型的变体。

这在榆树中可能吗?

不,不可能。在一些其他语言中,这可以使用 or-patterns 来实现(即使那样你仍然必须枚举和解构每个变体,但它们可以共享一个 body),但 Elm 的目标是成为一种比那些。

一个选项是将公共分支 body 提取到一个函数中:

upcaseTitle : Post -> Post
upcaseTitle post =
    let
        setTitle title =
            { post | title = String.toUpper title }
    in
    case post of
        Blog title body ->
            setTitle title

        Announcement title body ->
            setTitle title

另一种是定义一个单独的函数来仅提取标题:

getTitle : Post -> String
getTitle post =
    case post of
        Blog title body ->
            title

        Announcement title body ->
            title

upcaseTitle : Post -> Post
upcaseTitle post =
    { post | title = String.toUpper (getTitle post) }

但如果您的自定义类型的每个变体都相同,我会首先质疑该类型的设计。也许最好使用 post 类型只是一个字段的记录?

type PostType
    = Blog
    | Announcement

type Post =
    { title : String
    , body : String
    , postType : PostType
    }