我正在尝试为Monoid
定义HList Record
实例,但我收到了重叠的实例错误消息。
我的尝试(代码看起来很复杂,但它基本上是元组实例)
{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
import Data.Monoid
import Data.HList.FakePrelude
import Data.HList.Record
import Data.HList.Labelable
instance (Monoid v1, Monoid v2) =>
Monoid (Record '[Tagged (t1::Symbol) v1, Tagged (t2::Symbol) v2]) where
mempty = (Label :: Label (t1::Symbol)) .=. mempty
.*. (Label :: Label (t2::Symbol)) .=. mempty .*. emptyRecord
mappend a b = (Label :: Label (t1::Symbol))
.=. (a .!. (Label :: Label (t1::Symbol)))
`mappend` (b .!. (Label :: Label (t1::Symbol)))
.*.(Label :: Label (t2::Symbol))
.=. (a .!. (Label :: Label (t2::Symbol)))
`mappend` (b .!. (Label :: Label (t2::Symbol)))
.*. emptyRecord
错误讯息:
Database/Harehouse/Utils.hs:185:59:
Overlapping instances for HEq Symbol l0 t1 b
arising from a use of `.!.'
Matching instances:
instance [overlap ok] 'False ~ b => HEq k x y b
-- Defined in `Data.HList.TypeEqO'
instance [overlap ok] HEq k x x 'True
-- Defined in `Data.HList.TypeEqO'
(The choice depends on the instantiation of `t1, b, l0'
To pick the first instance above, use -XIncoherentInstances
when compiling the other instance declarations)
In the first argument of `mappend', namely
`(a .!. (Label :: Label (t1 :: Symbol)))'
In the second argument of `(.=.)', namely
`(a .!. (Label :: Label (t1 :: Symbol)))
`mappend` (b .!. (Label :: Label (t1 :: Symbol)))'
In the first argument of `(.*.)', namely
`(Label :: Label (t1 :: Symbol))
.=.
(a .!. (Label :: Label (t1 :: Symbol)))
`mappend` (b .!. (Label :: Label (t1 :: Symbol)))'
这是什么意思?我怎么解决这个问题 ? (我正在使用GHC 7.6.3)
答案 0 :(得分:1)
你需要ScopedTypeVariables
来获取mappend定义中的t1以匹配上面实例头中的t1。
此外,下一个HList版本将有一个类似于你的Monoid实例,除了它不限于长度为2的记录。http://code.haskell.org/HList/Data/HList/HList.hs是实现(Record
的实例是用GeneralizedNewtypeDeriving
)