10

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

{-# 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 }

我想匹配 aFoo但得到所有a,bc. 像这样的东西(无效的 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作为灵感。我正在尝试扩展该答案中的想法,以允许调用者任意提取m个字段中的n 个,以获得较大的m

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

4

1 回答 1

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
于 2016-08-12T03:25:24.317 回答