结合模式

时间:2015-08-10 01:38:31

标签: haskell pattern-synonyms

考虑以下数据类型和模式同义词:

{-# 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匹配,但要获取abc的全部内容。这样的事情(无效的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

但这会产生非详尽的匹配警告。但我们知道BarBaz是无可辩驳的,因此匹配每个都是无可辩驳的。

如果没有编译器警告,如何表达?

这样做的动机是对大数据类型的字段使用细粒度模式同义词,并允许调用者只提取与NamedFieldPuns的记录类似的所需字段。模式同义词还不支持记录语法,但它正在起作用:https://ghc.haskell.org/trac/ghc/ticket/8582

在我的情况下,我无法从模块中公开构造函数,因为我使用了&#34; smart-constructor&#34;模式,因此无法为呼叫者提供与NamedFieldPuns匹配的记录模式的好处。

请参阅https://stackoverflow.com/a/25161749/3198498作为灵感。我试图在该答案中扩展这个想法,允许呼叫者随意提取 m 字段的 n ,以获得较大的 m

编辑:事实证明,PatternSynonyms和详尽无遗检查存在相当广泛的问题:https://ghc.haskell.org/trac/ghc/ticket/10339 在启用警告的情况下编译时,这似乎使得用作字段提取器的模式同义词非常不愉快。

1 个答案:

答案 0 :(得分: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