gpt4 book ai didi

haskell - 我该如何解决这种类型类歧义?

转载 作者:行者123 更新时间:2023-12-02 01:11:37 25 4
gpt4 key购买 nike

这是我的最小示例:

{-# 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 函数的约束选择的那个。但我想不出解决它的方法。

我尝试过的事情:

  • 使用函数依赖从内部隐含外部;这接近于工作(提示需要 UndecidableInstances),但似乎不太正确;理想情况下,我真的希望能够有一种方法将相同的 inner 插入两个不同的 outer
  • 使用关联类型的同义词来做同样的事情;除了丑化类型签名(outer => Outer inner),我还摔倒了,因为我在一个实例中使用的 outer 有比 inner 更多的类型变量(其中一个是幻影),这意味着我无法在实例声明中合法地实例化关联类型
  • into 中使用 mergeScopedTypeVariables 添加显式类型签名,以将其绑定(bind)到 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

最佳答案

拥有一个不提及所有类变量的类方法很少是一个好主意(除非这些类变量由函数依赖唯一确定)。

解决方案是使类层次结构更加精确。在这里,您可以为 merge 创建第二个类:

class Mergeable a where
merge :: a -> a -> a

class Mergeable inner => Into outer inner where
factory :: inner -> outer

您也可以使用更通用的 Semigroup 类而不是专用的 Mergeable 类,但这取决于您的应用程序的细节和merge 的属性。

关于haskell - 我该如何解决这种类型类歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16789622/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com