考虑以下数据类型和模式同义词:
{-# 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匹配记录模式的好处。
以https://stackoverflow.com/a/25161749/3198498为灵感。我试图在这个答案中扩展这个想法,允许调用者任意提取n个m字段,以获得更大的值。
编辑:结果发现,PatternSynonyms和耗尽性检查存在一个相当大的问题:https://ghc.haskell.org/trac/ghc/ticket/10339,这似乎会使模式同义词在启用警告的情况下编译时非常不愉快。
发布于 2016-08-12 03:25:24
不确定这是否有帮助,但我会试试看。这些解决方案中的任何一个都是可以接受的吗?
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 chttps://stackoverflow.com/questions/31910536
复制相似问题