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

PolymorphicPerplexion

Tags:basicPolymorphismplaysavitalroleinautomatingverificationinLH.However,thankstoitsubiquity,weoftentakeitforgranted,anditcanbequitebafflingtofigureoutwhyverificationfailswithmonomorphicsignatures.Letmeexplainwhy,us

Tags:basic

Polymorphism plays a vital role in automating verification in LH. However, thanks to its ubiquity, we often take it for granted, and it can be quite baffling to figure out why verification fails with monomorphic signatures. Let me explain why, using a simple example that has puzzled me and other users several times.

22: 
23: module PolymorphicPerplexion where

A Type for Ordered Lists

Previously we have seen how you can use LH to define a type of lists whose values are in increasing (ok, non-decreasing!) order.

First, we define an IncList a type, with Emp (“empty”) and :< (“cons”) constructors.

38: data IncList a = Emp
39:                | (:<) { hd :: a, tl :: IncList a }
40: 
41: infixr 9 :<

Next, we refine the type to specify that each “cons” :< constructor takes as input a hd and a tl which must be an IncList a of values v each of which is greater than hd .

50: {-@ data IncList a = Emp 
51:                    | (:<) { hd :: a, tl :: IncList {v:a | hd <= v}}  
52:   @-}

We can confirm that the above definition ensures that the only legal values are increasingly ordered lists, as LH accepts the first list below, but rejects the second where the elements are out of order.

61: legalList :: IncList Int
62: (PolymorphicPerplexion.IncList GHC.Types.Int)legalList = GHC.Types.Int0 :< GHC.Types.Int1 :< GHC.Types.Int2 :< GHC.Types.Int3 :< {VV : forall a . (PolymorphicPerplexion.IncList a) | VV == Emp}Emp
63: 
64: illegalList :: IncList Int 
65: (PolymorphicPerplexion.IncList GHC.Types.Int)illegalList = GHC.Types.Int0 :< GHC.Types.Int1 :< GHC.Types.Int3 :< GHC.Types.Int2 :< {VV : forall a . (PolymorphicPerplexion.IncList a) | VV == Emp}Emp

A Polymorphic Insertion Sort

Next, lets write a simple insertion-sort function that takes a plain unordered list of [a] and returns the elements in increasing order:

76: insertSortP :: (Ord a) => [a] -> IncList a
77: forall a .
(GHC.Classes.Ord<[]> a) =>
[a] -> (PolymorphicPerplexion.IncList a)insertSortP [a]xs = foldr a -> (PolymorphicPerplexion.IncList a) -> (PolymorphicPerplexion.IncList a)insertP {VV : forall a . (PolymorphicPerplexion.IncList a) | VV == Emp}Emp {v : [a] | len v >= 0
           && v == xs}xs
78: 
79: insertP             :: (Ord a) => a -> IncList a -> IncList a
80: forall a .
(GHC.Classes.Ord<[]> a) =>
a -> (PolymorphicPerplexion.IncList a) -> (PolymorphicPerplexion.IncList a)insertP ay Emp       = {VV : a | VV == y}y :< {VV : forall a . (PolymorphicPerplexion.IncList a) | VV == Emp}Emp
81: insertP y (x :< xs)
82:   | {VV : a | VV == y}y <= {VV : a | VV == x}x         = {VV : a | VV == y}y :< {VV : a | VV == x}x :< {v : (PolymorphicPerplexion.IncList {VV : a | x <= VV}) | v == xs}xs
83:   | otherwise      = {VV : a | VV == x}x :< (PolymorphicPerplexion.IncList a)insertP {VV : a | VV == y}y {v : (PolymorphicPerplexion.IncList {VV : a | x <= VV}) | v == xs}xs

Happily, LH is able to verify the above code without any trouble! (If that seemed too easy, don’t worry: if you mess up the comparison, e.g. change the guard to x <= y LH will complain about it.)

A Monomorphic Insertion Sort

However, lets take the exact same code as above but change the type signatures to make the functions monomorphic , here, specialized to Int lists.

99: insertSortM :: [Int] -> IncList Int 
100: [GHC.Types.Int] -> (PolymorphicPerplexion.IncList GHC.Types.Int)insertSortM [GHC.Types.Int]xs = foldr GHC.Types.Int -> (PolymorphicPerplexion.IncList GHC.Types.Int) -> (PolymorphicPerplexion.IncList GHC.Types.Int)insertM {VV : forall a . (PolymorphicPerplexion.IncList a) | VV == Emp}Emp {v : [GHC.Types.Int] | len v >= 0
                       && v == xs}xs
101: 
102: insertM            :: Int -> IncList Int -> IncList Int 
103: GHC.Types.Int -> (PolymorphicPerplexion.IncList GHC.Types.Int) -> (PolymorphicPerplexion.IncList GHC.Types.Int)insertM GHC.Types.Inty Emp      = {v : GHC.Types.Int | v == y}y :< {VV : forall a . (PolymorphicPerplexion.IncList a) | VV == Emp}Emp
104: insertM y (x :< xs)
105:   | {v : GHC.Types.Int | v == y}y <= {v : GHC.Types.Int | v == x}x         = {v : GHC.Types.Int | v == y}y :< {v : GHC.Types.Int | v == x}x :< {v : (PolymorphicPerplexion.IncList {v : GHC.Types.Int | x <= v}) | v == xs}xs
106:   | otherwise      = {v : GHC.Types.Int | v == x}x :< (PolymorphicPerplexion.IncList GHC.Types.Int)insertM {v : GHC.Types.Int | v == y}y {v : (PolymorphicPerplexion.IncList {v : GHC.Types.Int | x <= v}) | v == xs}xs

Huh? Now LH appears to be unhappy with the code! How is this possible?

Lets look at the type error:

114:  /Users/rjhala/PerplexingPolymorphicProperties.lhs:80:27-38: Error: Liquid Type Mismatch
115:   
116:  80 |   | otherwise      = x :
	

LH expects that since we’re using the “cons” operator :< the “tail” value insertM y xs must contain values VV that are greater than the “head” x . The error says that, LH cannot prove this requirement of actual list insertM y xs .

Hmm, well thats a puzzler. Two questions that should come to mind.

  1. Why does the above fact hold in the first place?

  2. How is LH able to deduce this fact with the polymorphic signature but not the monomorphic one?

Lets ponder the first question: why is every element of insert y xs in fact larger than x ? For three reasons:

  1. every element in xs is larger than x , as the list x : was ordered,

  2. y is larger than x as established by the otherwise and crucially

  3. the elements returned by insert y xs are either y or from xs !

Now onto the second question: how does LH verify the polymorphic code, but not the monomorphic one? The reason is the fact (c)! LH is a modular verifier, meaning that the only information that it has about the behavior of insert at a call-site is the information captured in the (refinement) type specification for insert . The polymorphic signature:

156: insertP :: (Ord a) => a -> IncList a -> IncList a

via parametricity , implicitly states fact (c). That is, if at a call-site insertP y xs we pass in a value that is greater an x and a list of values greater than x then via polymorphic instantiation at the call-site, LH infers that the returned value must also be a list of elements greater than x !

However, the monomorphic signature

167: insertM :: Int -> IncList Int -> IncList Int

offers no such insight. It simply says the function takes in an Int and another ordered list of Int and returns another ordered list, whose actual elements could be arbitrary Int . Specifically, at the call-site insertP y xs LH has no way to conclude the the returned elements are indeed greater than x and hence rejects the monomorphic code.

Perplexity

While parametricity is all very nice, and LH’s polymorphic instanatiation is very clever and useful, it can also be quite mysterious. For example, q curious user Oisín pointed out that while the code below is rejected that if you uncomment the type signature for go then it is accepted by LH!

187: insertSortP' :: (Ord a) => [a] -> IncList a 
188: forall a .
(GHC.Classes.Ord<[]> a) =>
[a] -> (PolymorphicPerplexion.IncList a)insertSortP' = (PolymorphicPerplexion.IncList a)foldr a -> (PolymorphicPerplexion.IncList a) -> (PolymorphicPerplexion.IncList a)go {VV : forall a . (PolymorphicPerplexion.IncList a) | VV == Emp}Emp 
189:   where
190:     -- go :: (Ord a) => a -> IncList a -> IncList a
191:     a -> (PolymorphicPerplexion.IncList a) -> (PolymorphicPerplexion.IncList a)go ay Emp       = {VV : a | VV == y}y :< {VV : forall a . (PolymorphicPerplexion.IncList a) | VV == Emp}Emp
192:     go y (x :< xs)
193:       | {VV : a | VV == y}y <= {VV : a | VV == x}x     = {VV : a | VV == y}y :< {VV : a | VV == x}x :< {v : (PolymorphicPerplexion.IncList {VV : a | x <= VV}) | v == xs}xs
194:       | otherwise  = {VV : a | VV == x}x :< (PolymorphicPerplexion.IncList a)go {VV : a | VV == y}y {v : (PolymorphicPerplexion.IncList {VV : a | x <= VV}) | v == xs}xs

This is thoroughly perplexing, but again, is explained by the absence of parametricity. When we remove the type signature, GHC defaults to giving go a monomorphic signature where the a is not universally quantified, and which roughly captures the same specification as the monomorphic insertM above causing verification to fail!

Restoring the signature provides LH with the polymorphic specification, which can be instantiated at the call-site to recover the fact (c) that is crucial for verification.

Moral

I hope that example illustrates two points.

First, parametric polymorphism lets type specifications say a lot more than they immediately let on: so do write polymorphic signatures whenever possible.

Second, on a less happy note, explaining why fancy type checkers fail remains a vexing problem, whose difficulty is compounded by increasing the cleverness of the type system.

We’d love to hear any ideas you might have to solve the explanation problem!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 我们


推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了如何使用动态尺寸巧妙地将R中的数组子集化。作者通过解释数组的三个维度以及第三个维度的长度可变性,提出了一种周期性子集化数组的方法,并举例说明了如何创建第二个数组。这个方法对于制作模拟模型非常有用。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
author-avatar
卡吉米国际早教_763
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有