4

在接口 ( ) 中包含“智能构造函数”方法是一种优良传统class

class Collection c a  where 
  empty :: c a
  singleton :: a -> c a
  -- etc

将它们作为模式同义词提供会很好:

{-# LANGUAGE  PatternSynonyms  #-}
instance Ord a => Collection [] a  where
  empty = []
  singleton x = [x]
  pattern PEmpty = []
  pattern PSingleton x = [x]

但是您不能将 PatSyns 放在类中。我有一些工作,但它似乎有很多丑陋的代码。任何人都可以建议清理它的方法吗?(下面列出了具体的丑陋。)

{-# LANGUAGE  ViewPatterns  #-}
pattern PEmpty :: (Eq (c a), Collection c a) => c a
pattern PEmpty <- ((==) empty -> True)  where   
  PEmpty = empty                    

pattern PSingleton :: (Ord a, Collection c a) => a -> c a
pattern PSingleton x <- (isSingleton -> Just x)  where    
  PSingleton x = singleton x     

-- needs an extra method in the class:
  isSingleton :: c a -> Maybe a
-- instance ...
  isSingleton [x] = Just x
  isSingleton  _  = Nothing
  • 令人讨厌的是,这些必须是明确的双向模式;特别是因为 'under where' 行与实例重载如此直接可比。
  • 对于empty模式,我必须引入一个明确的(==)测试和支持Eq约束——以实现简单的模式匹配。(我想我可以调用一个isEmpty方法。)
  • 对于该singleton模式,我避免了显式(==)测试,但需要在类中的方法上加倍。
  • 我真的不喜欢ViewPatterns;我希望 PatSyns 可以提供一些方法来避免它们。
4

1 回答 1

4

如果您可以将模式同义词放在类实例中,那么您的解决方案将更加简单:您根本不需要emptyor在类中,因为它们可以用andsingleton来定义。唉,如您所知,这在当前的 GHC 中是不可能的。PEmptyPSingleton

照原样,您只能在类中定义函数和类型,并且无法访问构造函数(如列表示例中的[]:),您需要两个函数来定义模式同义词:一个用于从类型中提取数据,另一个用于嵌入它。

至于你关于丑陋的具体观点,有些是不可避免的,但对于其他人来说,可能有一个稍微干净的方法。

令人讨厌的是,这些必须是明确的双向模式;特别是因为 'under where' 行与实例重载如此直接可比。

唉,这是不可避免的。如果无法访问类中的构造函数,则需要显式使用双向模式。

对于empty模式,我必须引入一个明确的(==)测试和支持Eq约束——以实现简单的模式匹配。(我想我可以调用一个isEmpty方法。)

我个人认为您的代码使用isEmpty方法会更干净。对于它的价值,您可以根据需要使用默认签名,例如:

class Collection c a where
  ...
  isEmpty :: c a -> Bool
  default isEmpty :: Eq (c a) => c a -> Bool
  isEmpty = (==) empty

对于该singleton模式,我避免了显式(==)测试,但需要在类中的方法上加倍。

你这样说就像你有选择一样,但我认为你不能只用相等测试来编写这种模式。您正在尝试从未知集合中提取值,如果没有您的班级的支持,我看不出您如何做到这一点。一种extractSingleton方法似乎很合理,就像headMay :: [a] -> Maybe a(的安全版本head)很合理一样。

我真的不喜欢ViewPatterns;我希望 PatSyns 可以提供一些方法来避免它们。

这是另一个“唉”的时刻。很抱歉您不喜欢ViewPatterns,但它们几乎是编写双向模式同义词的唯一方法。


您没有提到的最重要的事情是围绕完整模式匹配的问题。您可能会发现,即使您拥有这些新模式,它们也会抛出关于非详尽模式匹配的各种警告。您可能想要定义一个更通用的类似“cons”的模式来破坏您的集合。然后,您可以为and添加一个COMPLETE编译指示。PEmptyPCons

于 2022-01-09T16:29:25.520 回答