繁体   English   中英

在Haskell中导入时隐藏类型类实例声明

[英]Hiding typeclass instance declarations while importing in Haskell

我正在尝试制作一个井字游戏,我决定构建单元格(板的元素)和板的类型如下:

data Cell  = X | O deriving (Show, Eq)
type Board = [[Maybe Cell]]

这里,Nothing表示空单元格(Just X)和(Just O)分别表示用X和O填充的单元格。

我想将(Maybe Cell)定义为monoid,如下所示:

instance Monoid (Maybe Cell) where
  mempty             = Nothing
  mappend Nothing x  = x
  mappend (Just x) _ = (Just x)

和董事会作为另一个幺半群

instance Monoid Board where
  mempty = [[Nothing, Nothing, Nothing]
           ,[Nothing, Nothing, Nothing]
           ,[Nothing, Nothing, Nothing]]
  mappend = zipWith (zipWith mappend) 
  -- where the right-hand-side mappend is the addition on (Maybe Cell)

我知道我可以在没有幺半群的情况下完全实现这一点,但我正在尝试探索这个领域,而这只是一种非常巧妙的方式来编写它。

我得到的问题是在GHC.Base已经定义了一个Maybe monoid实例,如下所示:

instance Semigroup a => Monoid (Maybe a)

这与我想要的定义截然不同,但它会导致重复的实例声明,所以我不能忽略它。

我要做的是隐藏GHC.BaseMonoid实例(Maybe a)以避免重复实例。 我尝试了很多搜索,但实际上找不到隐藏它的方法。 我无法隐藏所有Monoid或所有Semigroup ,因为我需要它们的功能,但我需要隐藏这个特定的实例声明。 有人可以帮我吗?

注意:我正在使用FlexibleInstances。

我标准的Haskell,类实例总是“完全全局” - 如果某个类型在某个地方有一个给定类的实例,那么这个实例随处可用。

因此,如果要定义单独的实例,则需要具有不同的类(通常不实用,包括在您的示例中)或不同的类型,这通常不是问题。 事实上,Haskell有一个专门用于此类事物的关键字newtype 您只需将type Board = [[Maybe Cell]]更改为

newtype Board = Board [[Maybe Cell]]

然后

instance Semigroup Board where
  Board l <> Board r = Board $ zipWith (zipWith mappend) l r
instance Monoid Board where
  mempty = Board [[Nothing, Nothing, Nothing]
                 ,[Nothing, Nothing, Nothing]
                 ,[Nothing, Nothing, Nothing]]
  mappend = (<>)

同样,您应该使用具有合适的Monoid实例的其他类型而不是Maybe Cell 那个实际上已经存在于基础库中了 ,但实际上并不是必需的:你可以为Cell本身创建一个半群(不是monoid!)实例,代表左偏,然后Maybe (因为GHC-8.4)自动拥有期望的行为。

instance Semigroup Cell where
  a <> _ = a

在2018年Haskell研讨会上发表的一篇论文中 ,实际上已经提议放宽这一点,允许本地选择的实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM