haskell - 无法从上下文中推导出(简单)类型类

标签 haskell

我在一个非常简单的示例中遇到错误,但我无法找出问题所在。我正在做的事情与 Monoid 中的 mempty 非常相似,这是一个简单的版本(我包括我的量化类型,以防与问题有关):

data Field a = Field String
              | forall b. EsMappable b => ReferenceField String (a -> b)

class EsMappable a where
    fields :: [Field a]

toMapping :: (EsMappable a) => a -> String
toMapping a = go "" fields
  where go str [] = str                        
        go str (ReferenceField name _ : xs) = go (name ++ str) xs
        go str (Field name : xs) =go (name ++ str) xs

我得到的错误是:

Could not deduce (EsMappable t0) arising from a use of ‘fields’
from the context (EsMappable a)
  bound by the type signature for
             toMapping :: EsMappable a => a -> String
  at search2.hs:11:14-42
The type variable ‘t0’ is ambiguous
In the second argument of ‘go’, namely ‘fields’
In the expression: go "" fields
In an equation for ‘toMapping’:
    toMapping a
      = go "" fields
      where
          go str [] = str
          go str (ReferenceField name _ : xs) = go (name ++ str) xs
          go str (Field name : xs) = go (name ++ str) xs

注意:如果我将 EsMapapble 类更改为: fields::a -> [Field a] ,然后在 toMapping 我更改了go ""(fields a),它有效。

我的问题:为什么我会收到此错误?这和mempty不一样吗?是什么阻止 GHC 正确解析字段

谢谢!

最佳答案

问题是编译器无法将您对字段的使用链接到您的参数a。您的 go 函数可以接受 any a[Field a],因此您需要以某种方式专门约束它与参数类型中的 a 相同。

您可以使用 ScopedTypeVariables 很好地做到这一点:

toMapping :: forall a. (EsMappable a) => a -> String
toMapping _ = go "" (fields :: [Field a])

您需要额外的 forall a 来明确使 a 类型变量具有作用域。这是为了向后兼容而对 ScopedTypeVariables 进行的限制。

如果您将 a 参数与 go 中的 Field a 值一起使用,这也不会成为问题。作为一个人为的示例,以下类型检查没有显式签名:

go str (ReferenceField name f : xs) = go (name ++ str) xs `const` f a

这会强制f采用a类型的参数,从而将整个列表限制为特定的a。因此,如果您确实愿意,实际上可以使用此技巧来避免 ScopedTypeVariables 扩展!但我不建议这样做:扩展几乎是无害的,并且使代码更加清晰。这个例子只是为了说明我的观点。

关于haskell - 无法从上下文中推导出(简单)类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25126628/

相关文章:

class - 是否存在一个表达式使得 <<表达式>> == <<表达式>> 始终为假?

haskell - 将函数与 Haskell 中的类型相关联

Haskell - 如何在函数体中使用类型签名中指定的类型参数?

list - 嵌套函数应用

haskell - 检查列表是否按照函数排序

haskell - 通用转换类型类

haskell - Opaleye 中链接表的数组聚合

haskell - 改进我的过滤器的 Haskell 实现

haskell - 函数式编程最好/最差解决哪些问题?

haskell - 理解 Haskell 中的类型级函数