这是我的最小例子:
{-# LANGUAGE MultiParamTypeClasses, RankNTypes #-}
import Control.Lens
class Into outer inner where
factory :: inner -> outer
merge :: inner -> inner -> inner
-- Given an inner item, a lens and an outer item, use factory to construct a new
-- outer around the inner if the Maybe outer is Nothing, or else use merge to combine
-- the argument inner with the one viewed through the lens inside the outer
into :: Into outer inner =>
inner -> Lens' outer inner -> Maybe outer -> Maybe outer
inner `into` lens = Just . maybe (factory inner) (over lens (merge inner))
无法使用以下错误进行编译:
GHCi, version 7.6.2: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main ( foo.hs, interpreted )
foo.hs:10:62:
Could not deduce (Into outer0 inner) arising from a use of `merge'
from the context (Into outer inner)
bound by the type signature for
into :: Into outer inner =>
inner -> Lens' outer inner -> Maybe outer -> Maybe outer
at foo.hs:9:9-84
The type variable `outer0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
In the second argument of `over', namely `(merge inner)'
In the second argument of `maybe', namely
`(over lens (merge inner))'
In the second argument of `(.)', namely
`maybe (factory inner) (over lens (merge inner))'
Failed, modules loaded: none.
Prelude>
我理解为什么发生此错误;对merge
的调用可能正在使用Into
的不同实例(与outer
相同但inner
}不同于整个约束所选择的实例into
功能。但我无法找到解决问题的方法。
我尝试过的事情:
outer
中的inner
;这接近工作(抱怨需要UndecidableInstances
),但似乎不太对劲;理想情况下,我真的希望能够将同一inner
推送到两个不同的outer
s outer
=> Outer inner
)之外,我也失败了,因为我在实例中使用的outer
有更多的类型变量(其中一个是幻像)比inner
,意味着我无法在实例声明中合法地实例化相关类型merge
into
ScopedTypeVariables
添加显式类型签名,并将into
与merge
的类型签名绑定;但由于outer
的类型未引用merge
,因此无效对于整个into
,我是否可以明确地使用instance (Hashable v, Eq v) => Into (VarInfo s k v) (HashSet v) where
-- VarInfo is just a record type with 2 fields, the second being a HashSet v
factory = VarInfo (return ())
merge = HashSet.intersection
的相同类型类实例?或者任何其他方式我可以约束类型系统需要这样做?理想情况下,我想保留这个类,所以我的实例声明仍然很简单:
{{1}}
答案 0 :(得分:5)
拥有一个没有提及所有类变量的类方法很少是个好主意(除非这些类变量由函数依赖项唯一确定)。
解决方案是使类层次结构更精确。在这里,您可以为merge
创建第二个类:
class Mergeable a where
merge :: a -> a -> a
class Mergeable inner => Into outer inner where
factory :: inner -> outer
您也可以使用更通用的Semigroup
类而不是ad-hoc Mergeable
类,但这取决于应用程序的详细信息和{{1}的属性}。