热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

将文字分配给GHC中的术语

出于好奇,为什么下面的程序1=0"hello"="world"由

出于好奇,为什么下面的程序

1 = 0
"hello" = "world"

由 GHC 有效和编译?这仅仅是一个错误还是一个功能?谢谢!

回答


这是允许的,因为它是语言规则的自然结果,并且没有足够的问题在语言规范中设置特殊情况来阻止它。

自然后果

有两种标准的定义:函数定义和数据定义。在函数定义中,您可以将模式作为参数写入等号左侧的函数。在数据定义中,您可以在等号左侧单独编写模式以匹配等号右侧的数据。所以,这些事情都是允许的:

x = 3
x@y = 3
[x, y, z] = [3, 4, 5]
[x, _, z] = [3, 4, 5]
[x, 4, z] = [3, 4, 5]
x:_ = "xsuffix"
x:"suffix" = "xsuffix"

数字文字和字符串文字是模式。(前一个 desugars 变成一个调用 的守卫(==)。)所以这些也是允许的:

3 = 3
x@3 = 3
[3, 4, 5] = [3, 4, 5]
"xsuffix" = "xsuffix"
-- and yes, these too
3 = 4
"xsuffix" = "lolno"

没有问题

与语言的所有其他部分一样,数据定义是惰性的:它们表示的模式匹配计算在需要之前不会执行(通过检查匹配绑定的变量之一)。由于"hello" = "world"1 = 0不绑定任何变量,它们代表的模式匹配计算——这将抛出异常——永远不会执行。所以避免允许它们并不是非常重要。

...除非它是

但是等等...我们说这是一个有效的模式:

x@3 = 3

而这个类似的发散并绑定一个变量:

x@3 = 4

怎么会一个被允许?这更难回答!我认为尝试考虑一些可以防止这种情况的语言规则是非常合理的。一般而言,合理且完备的规则当然是不可判定的,因为等式的右侧可以进行任意计算。但是您还可以做出其他选择;例如:


  • 不允许在数据定义中使用可反驳的模式。如果模式可能无法匹配,则它是可反驳的。例如,x是无可辩驳,x@y是无可辩驳,_是无可辩驳的,但x:y是可辩驳,True是可辩驳,()是可辩驳的(因为它发散在RHS是底部)。这是迄今为止最简单的,并且会排除x@3 = 4"hello" = "world"两者。不幸的是,它也会排除非常有用的东西,比如[x, y, z] = [3, 4, 5].

  • 实施终止检查器,并要求可反驳模式的 RHS 终止。如果您的分析可以决定某些计算终止——例如,通过发现其中的所有递归都是结构性的或其他东西,则存在终止检查算法的整个家庭手工业——那么您可以让编译器进行检查。如果它确实终止,编译器实际上可以在编译期间运行计算,并仔细检查给定的模式实际上是否与值匹配。这样做的缺点是终止检查算法非常复杂,因此这给编译器编写者带来了很大的负担,并且有些是人类难以预测的,这使得针对它的编程让用户感到沮丧。

  • 要求程序员证明匹配不能失败。您可以为程序员引入一种机制来为他们的程序编写证明,并要求他们证明匹配不会失败。这朝着依赖类型的方向发展;这种转变的两个主要成本通常是程序效率的降低,以及用这种语言编写程序需要更多的努力。

语言设计者做出了许多选择(不仅仅是在模式匹配语义中),这些选择在让程序员和编译器编写者的生活更轻松方​​面是错误的,但允许更多的程序抛出异常或永远不会完成。这是一个这样的地方——数据定义中允许可反驳的模式,即使这会导致崩溃,因为该策略的实现是有用的、简单的和可预测的。



  • @WillNess I have now added a section on why things like `x@1 = 0` are allowed. Thanks!




回答


因为这些文字是模式,所以您正在使用模式绑定。

letHaskell 中的绑定是惰性的,因此不执行实际的模式匹配。

但是如果我们强制匹配,它确实失败了:

> :{
let
x@1 = 0
in
1
:}
1 -- no assignment! NB
it :: Num a => a
> :{
let
x@1 = 0
in
x
:}
*** Exception: :87:1-7: Irrefutable pattern failed for pattern x@1

因为1确实不是 0

因此,这不是 GHC实现的错误或功能,而是 Haskell 语言本身的功能。



  • "let bindings in Haskell are lazy, so no actual pattern matching is performed." is not such explanation? I thought it was.





推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 非公版RTX 3080显卡的革新与亮点
    本文深入探讨了图形显卡的进化历程,重点介绍了非公版RTX 3080显卡的技术特点和创新设计。 ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • python的交互模式怎么输出名文汉字[python常见问题]
    在命令行模式下敲命令python,就看到类似如下的一堆文本输出,然后就进入到Python交互模式,它的提示符是>>>,此时我们可以使用print() ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文详细探讨了Java中的24种设计模式及其应用,并介绍了七大面向对象设计原则。通过创建型、结构型和行为型模式的分类,帮助开发者更好地理解和应用这些模式,提升代码质量和可维护性。 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 深入理解C++中的KMP算法:高效字符串匹配的利器
    本文详细介绍C++中实现KMP算法的方法,探讨其在字符串匹配问题上的优势。通过对比暴力匹配(BF)算法,展示KMP算法如何利用前缀表优化匹配过程,显著提升效率。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 本文深入探讨了Linux系统中网卡绑定(bonding)的七种工作模式。网卡绑定技术通过将多个物理网卡组合成一个逻辑网卡,实现网络冗余、带宽聚合和负载均衡,在生产环境中广泛应用。文章详细介绍了每种模式的特点、适用场景及配置方法。 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
author-avatar
林俊雯868043
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有