2017-06-23 90 views
9

考虑以下几点:傻重复记录的字段错误

{-# LANGUAGE DuplicateRecordFields #-} 

data A = A { name :: String } 

data B = B { name :: String } 

main = print $ name (A "Alice") 

在编译时,我收到以下消息(GHC上8.0.2)

duplicatedrecords.hs:7:16: error: 
    Ambiguous occurrence ‘name’ 
    It could refer to either the field ‘name’, 
          defined at duplicatedrecords.hs:5:14 
          or the field ‘name’, defined at duplicatedrecords.hs:3:14 

但是如果我修改main线如下:

main = print $ name ((A "Alice") :: A) 

编译成功进行。

这是为什么?类型签名:: A对我来说似乎是多余的,因为A构造函数肯定会告诉编译器(A "Alice")的类型为A。但由于某种原因,它有所作为。为什么是这样的,有没有一种方法可以让我编译而不用在任何地方乱扔额外的类型签名?

注:

值得一提的是,以下编译罚款:

data A = A { a_name :: String } 
data B = B { b_name :: String } 

class Name t where 
    name :: t -> String 

instance Name A where name = a_name 
instance Name B where name = b_name 

main = print $ name (A "Alice") 

我们甚至可以走得更远如下,让不同的结果类型:

{-# LANGUAGE TypeFamilies #-} 

data A = A { a_name :: String } 
data B = B { b_name :: Int } 

class Name t where 
    type family T t 
    name :: t -> T t 

instance Name A where 
    type T A = String 
    name = a_name 

instance Name B where 
    type T B = Int 
    name = b_name 

main = print $ name (A "Alice") 

似乎就像GHC一样,必须为每个数据类型中的每个记录的每个唯一记录名称和一个实例机械地添加一个类。这将意味着name x == name y并不意味着xy的类型是相同的,但是我期望在使用这个扩展的时候。

只是想知道是否有什么棘手的问题,我在这里错过了关于实现或者它只是需要有人做到这一点?

回答

6

-XDuplicateRecordFields当前不会从参数中推断出类型。

请参阅GHC user guide section about this extension

但是,我们不推断确定数据类型的参数类型,或者有任何方式将选择推迟到约束求解器。因此以下是不明确的:

但事情正在改善。因此,我们可以预期,最终获得所需的行为:

https://prime.haskell.org/wiki/TypeDirectedNameResolution

+0

感谢Shersh,这就是我正要说。目前的行为是克林顿寻找途中的中途之家。同时你可以看看他的镜头包。 – AntC