25

我在说的是无法定义:

data A = A {name :: String}
data B = B {name :: String}

我知道 GHC 只是将其简化为普通函数,解决此问题的惯用方法是:

data A = A {aName :: String}
data B = B {bName :: String}

class Name a where
  name :: a -> String

instance Name A where
  name = aName

instance Name B where
  name = bName

写完后我不太喜欢它……这种类型分类不能成为脱糖过程的一部分吗?


当我写一些 Aeson JSON 解析时,我想到了。如果只为每种数据类型派生FromJSON实例太容易了,我必须手动写出所有内容(目前 > 1k 行并计数)。在数据记录中具有类似name或简单的名称value并不少见。

http://www.haskell.org/haskellwiki/Performance/Overloading提到函数重载会引入一些运行时开销。但我实际上不明白为什么编译器无法在编译时解决这个问题并在内部给它们不同的名称。

这个 2012 年的 SO 问题或多或少地说明了历史原因,并指向了 2006 年的一个邮件线程。最近有什么变化吗?

即使会有一些运行时开销,大多数人也不会介意,因为大多数代码几乎不是性能关键。

是否有一些隐藏的语言扩展实际上允许这样做?我再次不确定......但我认为伊德里斯实际上是这样做的?

4

3 回答 3

4

许多,主要是次要原因。一个是更好的答案引发的问题,仅在第一个参数上重载不足以处理所有有用的情况。

你可以“脱糖”

data A { name :: String }
data B { name :: Text   }

进入

class Has'name a b | a -> b where
    name :: a -> b

data A { aName :: String }
instance Has'name A String where
    name :: aName

data B { bName :: Text   }
instance Has'name B Text   where
    name :: bName

但这需要尚未成为标准的 GHC 扩展(功能依赖项)。它将排除仅使用“名称”来创建记录、更新和模式匹配(查看模式可能会有所帮助),因为在这些情况下,“名称”不仅仅是一个函数。您可能可以使用模板 Haskell 完成一些非常相似的事情。

于 2013-01-31T15:12:20.453 回答
3

使用记录语法

data A { name :: String }

隐式定义一个函数

name :: A -> String

如果同时定义AB{ name :: String }我们有冲突的类型定义name

name :: A -> String
name :: B -> String

目前尚不清楚您建议的隐式类型类将如何工作,因为如果我们定义两种类型

data A { name :: String }
data B { name :: Text }

然后我们刚刚将问题转移到冲突的类型类定义:

class Has'name a where
     name :: a -> String

class Has'name a where
     name :: a -> Text

原则上,这可以通过一种或另一种方式解决,但这只是记录的几个棘手的冲突理想属性之一。当 Haskell 被定义时,人们决定最好有简单但有限的支持,而不是尝试设计更雄心勃勃和更复杂的东西。在不同的时间已经讨论了对记录的一些改进,并且存在常年的讨论,例如这个 Haskell Cafe 线程。也许会为 Haskell Prime 解决一些问题。

于 2013-01-25T23:27:50.633 回答
0

我发现最好的方法是使用预处理器来解决这个绝对相当愚蠢的问题。

Haskell 和 GHC 使这很容易,因为整个 Haskell 解析器都可以作为普通库使用。您可以只解析所有文件,执行重命名方案(例如 « data A { name :: String } » 和 « let a = A "Betty" in name a » 变成 « data A { a_Name :: String } » 和 « let a = A "Betty" in aName a ») 取决于应用名称函数的数据类型,使用类型解析器,并将它们写出来以进行编译。

但老实说,这应该集成到 GHC 中。你是对的:不包括在内是愚蠢的。

于 2013-05-03T15:09:02.653 回答