haskell - 如何告诉 Haskell 不要从两个模块导入同一个实例?

标签 haskell namespaces typeclass name-conflict

我正在使用以下类型类:

module T where
class T a where
  v :: a
T Int 的一个实例我实现的:
import T
import A (av)

instance T Int where
  v = 0

main = putStrLn (av ++ show v)

还有一个我想从中使用值的模块,它也有一个 T Int 的实例.
module A where
import T
instance T Int where
  v = 0
av = "value from A"

问题是这不起作用:
$ runghc Main.hs 

Main.hs:4:9:
    Duplicate instance declarations:
      instance T Int -- Defined at Main.hs:4:9-13
      instance T Int -- Defined at A.hs:3:9-13

Haskell 提示同一个实例有 2 个声明。我如何告诉他不要从 B 导入实例,或统一两个实例,或仅使用 Main 中的实例?

最佳答案

不幸的是,您无法控制实例的导入和导出方式。见 Do Haskell imports have side effects? .

这意味着您必须重构代码以确保实例仅在一个文件中定义。一般来说,最好只在定义类或数据类型的文件中定义一个实例——事实上,甚至有一个关于不遵循此规则的“孤立”实例的警告。 (查看 Orphaned instances in Haskell 进行长时间讨论,了解为什么应该避免孤立实例。)

但是,如果由于某种原因这是不可能的,您仍然可以任意选择其中一个文件来保留它,甚至创建一个新模块以供需要该特定实例的所有文件导入。

更一般地说,您将如何处理两个实例做不同事情的可能性,例如:

instance T Int where v = 0
{- And in a different file: -}
instance T Int where v = 1

在不显着改变 Haskell 类型类系统的工作方式的情况下,确实没有立即明显的方法来消除这两者的歧义。

由于您自己编写了其中一个实例,因此只需删除该实例即可。由于它与预定义的相同,因此只需将该模块导入您需要使用它的任何地方。

关于haskell - 如何告诉 Haskell 不要从两个模块导入同一个实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16431234/

相关文章:

postgresql - 理解 Haskell postgresql 连接函数类型错误

haskell - IO monad 的逻辑 AND 严格性

haskell - 如何在 Haskell 中创建更具可读性的多行字符串?

c++ - 在不同的命名空间中测试特定的类名(SFINAE?)

function - Haskell 类型类

c++ - 如何将原始 Haskell 绑定(bind)编译到 OpenCV 又名 GitHub 成员 arjuncomar 的 OpenCV-Raw 仓库

namespaces - Clojure:函数的全限定名

php - PHP 中的命名空间和 set_include_path() 有问题

scala - Shapeless 中 TypeClass 特征的 emptyCoproduct 和 coproduct 方法的目的是什么

haskell - 在 Haskell 中,Integral typeclass 是否意味着 Show typeclass?