Объединение моделей

Рассмотрим следующие синонимы типа данных и шаблона:

{-# LANGUAGE PatternSynonyms, NamedFieldPuns #-}

data Foo = Foo {
      a :: Int
    , b :: String
    , c :: Maybe Bool
}

pattern Bar a b <- Foo { a, b }
pattern Baz c <- Foo { c }

Я хотел бы соответствовать Foo но получить все a, b, а также c, Как то так (недопустимый Haskell):

showit :: Foo -> String
showit (Bar a b & Baz c) = show a ++ b ++ show c

Одним из вариантов является использование ViewPattern:

dup :: a -> (a, a)
dup a = (a, a)

showall' :: Foo -> String
showall' (dup -> (Bar a b, Baz c)) = show a ++ b ++ show c

Но это приводит к неисчерпывающему предупреждению о совпадении. Но мы знаем, что Bar а также Baz неопровержимы, поэтому сопоставление каждого также неопровержимо.

Как это можно выразить без предупреждения компилятора?

Мотивация для этого состоит в том, чтобы иметь детализированные синонимы шаблона для полей большого типа данных и позволить вызывающим абонентам извлекать только нужные поля, аналогичные записям с NamedFieldPuns, Шаблонные синонимы еще не поддерживают синтаксис записи, но он находится в разработке: https://ghc.haskell.org/trac/ghc/ticket/8582

В моем случае я не могу выставить конструктор из модуля, так как я использую шаблон "умный конструктор", и, следовательно, не могу дать вызывающим сторонам преимущество сопоставления шаблона записи с NamedFieldPuns,

См. /questions/18587705/mozhno-li-eksportirovat-konstruktoryi-dlya-sopostavleniya-s-obraztsom-no-ne-dlya-postroeniya-v-modulyah-haskell/18587723#18587723 в качестве вдохновения. Я пытаюсь расширить идею в этом ответе, чтобы позволить вызывающим абонентам произвольно извлечь n из m полей, для больших m.

Редактировать: Оказывается, существует довольно широкая проблема с PatternSynonyms и полные проверки: https://ghc.haskell.org/trac/ghc/ticket/10339 Это, кажется, делает синонимы шаблонов, используемые в качестве экстракторов полей, очень неприятными при компиляции с включенными предупреждениями.

1 ответ

Не уверен, что это вообще полезно, но я попробую. Будет ли приемлемо любое из этих решений?

showit :: Foo -> String
showit x@(Bar a b) = show a ++ b ++ show (c x)

showit' :: Foo -> String
showit' x@(Bar a b) = show a ++ b ++ showthat x
  where
    showthat (Baz c) = show c
Другие вопросы по тегам