考虑以下数据类型和模式同义词:
{-# 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
在我的情况下,我无法从模块中公开构造函数,因为我使用了&#34; smart-constructor&#34;模式,因此无法为呼叫者提供与NamedFieldPuns
匹配的记录模式的好处。
请参阅https://stackoverflow.com/a/25161749/3198498作为灵感。我试图在该答案中扩展这个想法,允许呼叫者随意提取 m 字段的 n ,以获得较大的 m 。
编辑:事实证明,PatternSynonyms
和详尽无遗检查存在相当广泛的问题:https://ghc.haskell.org/trac/ghc/ticket/10339
在启用警告的情况下编译时,这似乎使得用作字段提取器的模式同义词非常不愉快。
答案 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