Как извлечь значение из нескольких вариантов пользовательского типа? - PullRequest
1 голос
/ 18 марта 2019

У меня есть тип, как,

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 типам и извлекает общие String, title, поскольку оно является общим для всех вариантов моего типа объединения.

Возможно ли это в вязе?

1 Ответ

6 голосов
/ 18 марта 2019

Нет, не возможно. В некоторых других языках это может быть достигнуто с помощью шаблонов or (даже тогда вы все равно должны перечислять и деконструировать каждый вариант, но они могут разделять одно тело), ​​но Elm стремится быть более простым языком, чем те.

Один из вариантов - извлечь общее тело ветви в функцию:

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) }

Но если все варианты вашего пользовательского типа идентичны, я бы начал с вопроса о дизайне этого типа. Может быть, было бы лучше использовать запись, в которой тип записи - это просто поле?

type PostType
    = Blog
    | Announcement

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