请考虑以下事项:
{-# 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
并不意味着x
和y
的类型相同,但无论如何我都希望使用此扩展程序。
只是想知道我在这里是否有任何棘手的问题,或者只是需要有人这样做?
答案 0 :(得分:6)
-XDuplicateRecordFields
目前无法从参数中推断出类型。
请参阅GHC user guide section about this extension。
但是,我们不推断确定数据类型的参数类型,或者有任何方法将选择推迟到约束求解器。因此,以下是不明确的:
但事情正在改善。所以我们可能期望并最终得到理想的行为: