多态模式匹配导致类型不明确

2024-02-23

(灵感来自无法匹配具有约束的多态元组 https://stackoverflow.com/questions/57137421/cannot-match-on-polymorphic-tuples-with-constraints,并基于随后的comment https://stackoverflow.com/questions/57137421/cannot-match-on-polymorphic-tuples-with-constraints#comment100805403_57138105根据我自己的回答。)

考虑以下最小示例:

test :: (Show a, Show b) => (a -> String, b -> String)
test = (show,show)

(resX, resY) = test

这会导致以下错误:

    • Ambiguous type variable ‘a0’ arising from a use of ‘test’
      prevents the constraint ‘(Show a0)’ from being solved.
      Relevant bindings include
        resX :: a0 -> String (bound at so.hs:25:2)
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance Show Ordering -- Defined in ‘GHC.Show’
        instance Show Integer -- Defined in ‘GHC.Show’
        instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
        ...plus 22 others
        ...plus 17 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: test
      In a pattern binding: (resX, resY) = test
   |
25 | (resX, resY) = test
   |                ^^^^

这是有道理的:模式匹配不会受到限制a or b无论如何,所以他们是模棱两可的。但我该如何摆脱这个错误呢?几乎每次尝试通过添加类型签名来解决此问题都会产生另一个错误。例如:

-- attempt 1
test :: (Show a, Show b) => (a -> String, b -> String)
test = (show,show)

resX :: Show a => a -> String
resY :: Show b => b -> String
(resX, resY) = test

-- attempt 2
test :: (Show a, Show b) => (a -> String, b -> String)
test = (show,show)

(resX, resY) = test :: (Show a, Show b) => (a -> String, b -> String)

那么:我怎样才能摆脱歧义错误呢?而为什么上述尝试都失败了呢?


思考代码在运行时的实际工作原理很有启发性。类型类有字典传递语义。优雅的代码

class Foo a where
    foo :: a -> Int

instance Foo Int where
    foo = id

useFoo :: Foo a => a -> IO ()
useFoo x = print (foo x)

callFoo = useFoo (123 :: Int)

被编译成非类代码。

data Foo_ a = Foo_ { foo :: a -> Int }

foo_Int :: Foo_ Int
foo_Int = Foo_ { foo = id }

useFoo :: Foo_ a -> a -> IO ()
useFoo dict x = print (foo dict x)

callFoo = useFoo foo_Int 123

“胖箭”=>在运行时实际上意味着与“瘦骨嶙峋的箭头”完全相同的东西->。唯一的区别是=>的参数由约束求解器隐式传递。

所以让我们想想你的Show从这个角度看例子。像这样的类型test :: (Show a, Show b) => (a -> String, b -> String)真正意思test :: (Show_ a, Show_ b) -> (a, String, b -> String)。您不能将该函数分解为一对函数(Show_ a -> a -> String, Show_ b -> b -> String)。函数体可能会同时使用两者Show_返回结果之前必须先提供字典,因此您必须先提供两者,然后才能获得(a -> String, b -> String) out.

当推断类型时resx,类型检查器会得出resx :: (Show a, Show b) => a -> String- 它需要范围内的两个实例才能调用test。显然这是一种模棱两可的类型。b没有出现在右侧=>, so at resx的调用站点永远不会有足够的本地类型信息来成功调用它。

你可能会反对那个should在这种情况下能够进行这样的因式分解。的两半test身体不能互相利用Show实例,因为Show的方法仅将其类型参数作为输入进行讨论,并且输入不在元组错误的一半范围内。但这是关于运行时行为的参数化的复杂论证,并且仅适用于这种特定情况。这不是编译器擅长的那种愚蠢的语法指导推理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多态模式匹配导致类型不明确 的相关文章

随机推荐

  • 沿 NumPy 数组的一个轴按位或

    对于给定的 NumPy 数组 很容易沿一维执行 正常 求和 例如 X np array 1 0 0 0 2 2 0 0 3 X sum 0 array 1 2 5 X sum 1 array 1 4 3 相反 是否有一种 有效 的方法来类似
  • TFS 分支图上显示的排除分支

    我正在使用TFS2010 通过VS2013 当我进入我的主分支时 Branching and Merging gt View Hierarchy 它显示了一些已删除的分支 它们很早就被我自己排除了 但我无法将它们从图中删除 以下是层次结构视
  • 验证Web服务器中的路径遍历漏洞

    我想验证我的 Web 应用程序不存在路径遍历漏洞 我正在尝试使用curl为此 像这样 curl v http www example com directory 我希望显式向 directory URL 用于测试涉及代理的特定 nginx
  • 创建扩展 postgis 失败,

    I am on Ubuntu 18 04与psql PostgreSQL 12 2 Ubuntu 12 2 2 pgdg18 04 1 Running temba create extension postgis 失败并出现以下错误 ERR
  • iPhone 5 屏幕尺寸

    我正在开发适用于 iphone4 和 iPhone 5 的应用程序 我使用以下代码来获取屏幕尺寸 CGRect screenBounds UIScreen mainScreen bounds 我使用 iPhone 5 模拟器 但它显示的是
  • 如何自定义Action Bar副标题字体?

    我创建了一个 ActionBar android support v7 widget Toolbar 如下
  • 开发和 Azure Web 应用程序中的 ContentRootPath 不同

    当我将 Dot Net Core Web 应用程序部署到 Azure 时 Environment ContentRootPath变量设置为 myproject wwwroot 但在开发过程中 只是 myproject 为什么 Azure 部
  • InvalidOperationException 与 ArgumentException [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我知道摘要和描述 但是如果 ARGU
  • 如何恢复打乱的数据流管道的顺序?

    我有一个数据流管道 由多个处理异构文档 XLS PDF 等 的块组成 每种类型的文档均由专门的人员处理TransformBlock 在管道的末端我有一个ActionBlock它接收所有处理后的文档 并将它们一一上传到网络服务器 我的问题是
  • 轻量级 C++ SAX XML 解析器

    我知道至少三个轻量级 C XML 解析器 RapidXML http rapidxml sourceforge net TinyXML http sourceforge net projects tinyxml and PugiXML ht
  • Ruby 1.9.1 中的枚举器如何工作?

    这个问题不是关于如何在 Ruby 1 9 1 中使用枚举器 而是我很好奇它们是如何工作的 这是一些代码 class Bunk def initialize h 1 100 end def each if block given enum f
  • 如何在单击时移除按钮周围的焦点

    单击按钮后 我的按钮周围都会突出显示 这是在 Chrome 中
  • 如何使用“apollo-server”加载 .graphql 文件?

    我目前正在使用单独的加载 GraphQL 架构 graphql文件 但它封装在字符串中 schema graphql const schema type CourseType id String name String type Query
  • 单独读取 csv 文件中的列名

    我有一个包含以下列的 csv 文件 身份证号 姓名 年龄 性别 接下来是上面各列的许多值 我试图单独读取列名并将它们放入列表中 我正在使用 Dictreader 这给出了正确的详细信息 with open details csv as cs
  • 如何使用图像和标签制作自定义 UIBarButtonItem?

    我想制作一个包含图像和文本的自定义 UIBarButtonItem 如下所示 我尝试子类化 UIBarButtonItem 并重写此方法 UIView customView if self storedView UIView temp UI
  • TreeMap 中的重复键[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有下面的树图代码 我在其中存储重复的密钥 它似乎覆盖了现有的密钥 TreeMap
  • 使用 JavaScript 更改 SharePoint 列表的权限

    我有一个创建列表的应用程序 我希望应用程序也将列表权限设置为仅允许管理员对列表进行更改 我知道如何隐藏列表 但我知道这不会阻止聪明的用户输入列表的 URL 并进行修改 我没有看到使用 JavaScript 更改列表权限的方法 我可以使用的列
  • 如何在 Silverlight 应用程序中显示容器的 Azure blob 列表?

    如何在 Silverlight 应用程序中显示容器的 Azure blob 列表 我知道如何在常规 Net 中执行此操作 但我需要它在银光中 我可以上传 但我想要显示已上传内容的列表 对于 Silverlight 来说是这样的 CloudS
  • 如何修复 SVN 导入行结尾错误?

    我必须导入一个巨大的 SVN 存储库 并将其从一台服务器传输到另一台服务器 所以我从旧服务器导出它 svnadmin dump gt archive svn 并将其导入新的 svnadmin load lt archive svn 在导入过
  • 多态模式匹配导致类型不明确

    灵感来自无法匹配具有约束的多态元组 https stackoverflow com questions 57137421 cannot match on polymorphic tuples with constraints 并基于随后的c