Haskell 如何正确绑定此类型变量?

Haskell 如何正确绑定此类型变量?,haskell,type-variables,Haskell,Type Variables,我一直在挖掘一些旧代码(坦率地说,我对一些设计决策感到遗憾),但我意识到我永远无法编译最终的函数,我真的不明白为什么。我有ScopedTypeVariables,它通常能为我解决这样的问题 {-#语言模板haskell} {-#语言多段类型类,FlexibleInstances,undedicatableInstances,flexibleContext,RankNTypes#-} {-#语言派生Traversable,派生策略,ScopedTypeVariables#-} {-#语言功能依赖性

我一直在挖掘一些旧代码(坦率地说,我对一些设计决策感到遗憾),但我意识到我永远无法编译最终的函数,我真的不明白为什么。我有ScopedTypeVariables,它通常能为我解决这样的问题

{-#语言模板haskell}
{-#语言多段类型类,FlexibleInstances,undedicatableInstances,flexibleContext,RankNTypes#-}
{-#语言派生Traversable,派生策略,ScopedTypeVariables#-}
{-#语言功能依赖性}
{-#语言允许歧义类型}
导入前奏隐藏((+),(*))
导入代数
导入控制.Lens.TH(MakeLens)
导入数据.半群(半群,())
导入数据.Monoid(mempty,mappend)
导入数据代理(Proxy)
导入数据。函数(打开)
将限定的Data.IntMap作为IM导入
导入控制。镜头(IxValue、索引、Ixed(..)、遍历、Iso、查看、查看)
类别(Ixed g)=>网格g,其中
--先存储x,然后存储y
gridIso::Iso'g(IM.IntMap(IM.IntMap(IxValue g)))
storageVector::(索引g)->Vector2D Int
{-#内联网格#-}
gridIx::forall g。(网格g)=>(索引g)->遍历'g(IXG值)
gridIx v=gridIso。(ix x)。(九)
其中(Vector2D x y)=存储向量v
相反,我得到的是:

/mnt/c/Users/me/advent2018/src/Vector.hs:92:41: error:
    • Couldn't match expected type ‘Index g0’
                  with actual type ‘Index g’
      NB: ‘Index’ is a non-injective type family
      The type variable ‘g0’ is ambiguous
    • In the first argument of ‘storageVector’, namely ‘v’
      In the expression: storageVector v
      In a pattern binding: (Vector2D x y) = storageVector v
    • Relevant bindings include
        v :: Index g
          (bound at /mnt/c/Users/me/advent2018/src/Vector.hs:91:8)
        gridIx :: Index g -> Traversal' g (IxValue g)
          (bound at /mnt/c/Users/me/advent2018/src/Vector.hs:91:1)

这里发生的事情是,为了调用
storageVector
,编译器必须选择
Grid
的实例,但它不能

通常情况下,参数类型足以选择实例,但在本例中,参数的类型为
索引g
,而
索引
是非内射类型族(如错误消息所述),这意味着您可以从
g
转到
索引g
,但不能返回。换句话说,仅仅通过知道
索引g
是无法确定
g
是什么

因此编译器不能选择
网格
实例并拒绝该程序

为了帮助编译器实现这一点,可以显式指定应该用于实例查找的类型。为此,请使用
TypeApplications
扩展名:

    where (Vector2D x y) = storageVector @g v
这将告诉编译器,它应该对相同的
g
使用实例
Grid g


请注意,要使其发挥作用,必须使用
forall
关键字声明
g
,您已经在这样做了

请发布
Vector2D
的定义。我现在无法设置项目来验证这一点,但请尝试
storageVector@gv
(您需要为此启用
TypeApplications