Совпадение записей в Haskell

Я ищу способ упростить функциональные шаблоны, когда фактические данные не требуются:

data X = A | B String | C Int Int String
myfn :: X -> Int
myfn A = 50
myfn (B _) = 200
myfn (C _ _ _) = 500

Есть ли способ сделать более простой шаблон для сопоставления C, просто отбрасывая значения?

hsdev добавляет подсказку "Подсказка: используйте шаблоны записей", но Google не помог мне там.

Ответ 1

Вы можете использовать такие шаблоны записей:

data X = A | B {name :: String} | C {x::Int, y::Int, name::String}

myfn :: X -> Int
myfn A = 50
myfn B{} = 200
myfn C{} = 500

Образцы записей позволяют присваивать имена полям конструкторов. вы также можете делать такие вещи, как:

myfn C{name=n} = length n

поэтому вы можете видеть, что вы можете сопоставлять шаблоны только в определенном поле, которое вам нужно.

Примечание. Вы можете использовать пустой шаблон записи даже с типами данных, которые не используют синтаксис записи:

data A = A Int | B Int Int

myfn A{} = 1
myfn B{} = 2

Это отлично. Существует ряд других расширений, связанных с шаблонами записи:

  • RecordWildCards позволяет писать такие вещи, как C{..} что эквивалентно шаблону: C{x=x, y=y, name=name}, т. RecordWildCards всем полям, и теперь вы имеете в области x со значением, соответствующим для поля x и т.д.

  • NamedFieldPuns позволяет вам написать C{name} чтобы он был эквивалентен C{name=name}, так что name теперь находится в области видимости и содержит значение, сопоставляемое для поля name.

Имейте в виду, что использование шаблонов записей не мешает вам использовать ваши конструкторы позиционным способом, поэтому вы все равно можете написать:

myfn (B _) = 200

Это добавляет только функциональность.