【问题标题】:Hiding typeclass instance declarations while importing in Haskell在 Haskell 中导入时隐藏类型类实例声明
【发布时间】:2019-02-22 21:22:05
【问题描述】:

我正在尝试制作井字游戏,我决定为单元格(棋盘的元素)和棋盘构造类型如下:

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

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

我想将 (Maybe Cell) 定义为一个幺半群,如下所示:

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

Board 作为另一个幺半群

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)

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

我得到的问题是 Maybe 的 monoid 实例已经在 GHC.Base 中定义如下:

instance Semigroup a => Monoid (Maybe a)

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

我要做的是从GHC.Base 中隐藏(Maybe a) 的Monoid 实例以避免重复实例。我尝试了很多搜索,但无法真正找到隐藏它的方法。我无法隐藏所有Monoid 或所有Semigroup,因为我需要它们的功能,但我需要隐藏这个特定的实例声明。谁能帮我解决这个问题?

注意:我使用的是 FlexibleInstances。

【问题讨论】:

  • 您无法隐藏instance 声明。您可以做的是使用 newtype 来“包装”基础类型。这甚至在标准库中也做了很多 - 例如 Sum 和 Product 类型都是 Int 的包装器(实际上是 Num 的任何实例),具有不同的 Monoid 实例。
  • 哦,您的 Monoid 实例 Maybe Cell 已经作为 newtype 包装器存在:hackage.haskell.org/package/base-4.12.0.0/docs/…
  • @RobinZigmond 哇!那太快了!它是正确的; First 完全解决了这个问题。非常感谢!

标签: haskell typeclass monoids semigroup


【解决方案1】:

我是标准的 Haskell,类实例总是“完全全局的”†——如果一个类型有一个给定类的实例somewhere,那么这个实例会在任何地方使用。

所以,如果你想定义一个单独的实例,你需要有一个不同的类——通常不实用,包括在你的例子中——或者一个不同的类型,这通常不是问题。事实上,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。那个实际上是exists already in the base library,但这并不是真正必要的:您可以为Cell 本身创建一个代表左偏的半群(不是幺半群!)实例,然后Maybe 将(自GHC-8.4 起)自动拥有期望的行为。

instance Semigroup Cell where
  a <> _ = a

†实际上有人提议放宽这一点,允许在a paper presented at the 2018 Haskell Symposium中选择本地实例。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2022-08-12
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 2018-01-29
相关资源
最近更新 更多