【发布时间】:2012-08-27 08:55:27
【问题描述】:
考虑以下代码:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.HList.GhcSyntax((.!.),(.=.),(.*.))
import Data.HList.Record(emptyRecord)
import Data.HList.TypeCastGeneric1
import Data.HList.TypeEqGeneric1
import Data.HList.Label5
data Hello1 = Hello1
data Hello2 = Hello2
record = (Hello1 .=. "Hello1") .*. (Hello2 .=. "Hello2") .*. emptyRecord
f1 = $([| (\r1 -> (r1 .!. Hello1)) |])
main = print $ f1 record
这可以正常编译并按预期打印出“Hello1”。
但是,添加以下行 (GHC 7.4.1) 会产生编译错误:
f2 = $([| (\r2 -> (r2 .!. Hello2)) |])
给出的错误是:
error.hs:16:1:
Could not deduce (Data.HList.Record.HasField Hello2 r0 v0)
arising from the ambiguity check for `main'
from the context (Data.HList.Record.HasField Hello2 r v)
bound by the inferred type for `main':
Data.HList.Record.HasField Hello2 r v => IO ()
at error.hs:(16,1)-(20,38)
Possible fix:
add an instance declaration for
(Data.HList.Record.HasField Hello2 r0 v0)
When checking that `main'
has the inferred type `forall r v.
Data.HList.Record.HasField Hello2 r v =>
IO ()'
Probable cause: the inferred type is ambiguous
error.hs:16:1:
Could not deduce (Data.HList.Record.HasField Hello2 r0 v0)
arising from the ambiguity check for `f1'
from the context (Data.HList.Record.HasField Hello2 r v)
bound by the inferred type for `f1':
Data.HList.Record.HasField Hello2 r v =>
Data.HList.Record.Record
(Data.HList.HListPrelude.HCons
(Data.HList.Record.LVPair Hello1 [Char])
(Data.HList.HListPrelude.HCons
(Data.HList.Record.LVPair Hello2 [Char])
Data.HList.HListPrelude.HNil))
-> [Char]
at error.hs:(16,1)-(20,38)
Possible fix:
add an instance declaration for
(Data.HList.Record.HasField Hello2 r0 v0)
When checking that `f1'
has the inferred type `forall r v.
Data.HList.Record.HasField Hello2 r v =>
Data.HList.Record.Record
(Data.HList.HListPrelude.HCons
(Data.HList.Record.LVPair Hello1 [Char])
(Data.HList.HListPrelude.HCons
(Data.HList.Record.LVPair Hello2 [Char])
Data.HList.HListPrelude.HNil))
-> [Char]'
Probable cause: the inferred type is ambiguous
为什么添加f2 行会导致编译错误?
注意:Haskell 模板部分在这里可能看起来很傻,但它们是更复杂的模板 Haskell 的简化,它确实适用于元组。我已经发布了我可以构建的最简单的示例,但仍然显示错误。我意识到在这种情况下删除模板 Haskell 可以解决问题,但这不是我真实代码中的选项。
编辑:
另外,以下编译失败。为什么会这样:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.HList.GhcSyntax((.!.),(.=.),(.*.))
import Data.HList.Record(emptyRecord)
import Data.HList.TypeCastGeneric1
import Data.HList.TypeEqGeneric1
import Data.HList.Label5
data Hello1 = Hello1
data Hello2 = Hello2
data Hello3 = Hello3
record1 = (Hello1 .=. "Hello1") .*. (Hello2 .=. "Hello2") .*. emptyRecord
record2 = (Hello1 .=. "Hello1") .*. (Hello2 .=. "Hello2") .*. (Hello3 .=. "Hello3") .*. emptyRecord
f1 = $([| (\r1 -> (r1 .!. Hello1)) |])
main = print $ (f1 record1, f1 record2)
【问题讨论】:
-
添加
f2的定义后,你在任何地方使用它吗?如果没有,如果你给f2一个显式的类型注释,它是否有效? -
@DanielWagner:使用
f2似乎有帮助。但是,我发现了其他问题。请参阅stackoverflow.com/questions/12144250/… 一个不涉及 HList 的问题示例。 -
@DanielWagner:再想一想,也许这个问题是一个转移注意力的问题,尽管它可能是相关的。我找到了一种解决方法并将其作为我自己问题的答案,这并不理想,但对我的问题来说是可行的解决方案。
标签: haskell template-haskell hlist