haskell - Haskell:类型签名是完全的是什么意思?
问题描述
我有以下代码,它概述了布尔和算术表达式的语言:
data Exp a where
Plus :: Exp Int -> Exp Int -> Exp Int
Const :: (Show a) => a -> Exp a
Not :: Exp Bool -> Exp Bool
And :: Exp Bool -> Exp Bool -> Exp Bool
Greater :: Exp Int -> Exp Int -> Exp Bool
以下是仅计算算术表达式的函数的代码:
evalA (Plus a b) = evalA a + evalA b
evalA (Const a) = a
我试图弄清楚应该给予什么类型的签名以evalA
使其完全。但是,我不知道类型签名完全意味着什么。任何见解都值得赞赏。
解决方案
另一个答案解释说“总计”是函数的属性,而不是类型签名;然后继续说,如果你希望你的函数是完整的,你必须覆盖 GADT 的其他构造函数。但这还不是全部。
真实的故事是,对于像 Haskell 这样具有高级类型系统的语言,“total”是函数和类型签名之间的关系。所以它确实不是类型签名的属性(说“这个类型签名是完全的”是没有意义的);但它也不是函数的属性(孤立地说“这个函数是全部的”!1是没有意义的)。
所以现在,让我们回到你的问题。你说:
data Exp a where
Plus :: Exp Int -> Exp Int -> Exp Int
Const :: (Show a) => a -> Exp a
Not :: Exp Bool -> Exp Bool
And :: Exp Bool -> Exp Bool -> Exp Bool
Greater :: Exp Int -> Exp Int -> Exp Bool
evalA (Plus a b) = evalA a + evalA b
evalA (Const a) = a
鉴于我们更新的理解,我们现在可以提出一个新的、更好的、更精确的问题,即:是否存在一个类型签名evalA
,当与此实现配对时,会导致配对是完全的?这个更好的问题的答案是肯定的,这与另一个答案中的说法相反,即您必须实施更多的evalA
. 特别是,如果我们写
evalA :: Exp Int -> Int
evalA (Plus a b) = evalA a + evalA b
evalA (Const a) = a
那么evalA
对有限输入的任何类型良好的应用程序都将在有限时间内产生一个非底部答案。(这是函数“总计”的一种合理含义。)
为什么我们可以忽略Not
、And
和Greater
情况?为什么,因为我们要求输入具有 type Exp Int
,以及任何其外部构造函数为 、 或实际上将具有 type 的类型良好的术语Not
——And
因此Greater
应用Exp Bool
程序将不是类型良好的。所以这不会因为不详尽的模式匹配错误而崩溃,因为人们可能会担心!
1可以说“这个函数,给定任何类型检查的类型签名,是全部的”。事实上,通常说“这个函数是全部的”是一种方便的简写方式。另一个答案显示了无论给出什么(正确的)类型签名,如何使您的函数总计。
推荐阅读
- exception - RxJava2 Flowable onErrorReturn 未调用
- python - 如何使用python对复杂列表进行排序?
- python - 如何从字典中仅提取某些值(python)
- python - 如何在 pex 文件中使用 ubuntu 包
- javascript - 将 JSON 转换为 ANY 类型的 TW 对象
- angular - 社交登录 - 权限
- firebase - 在 Unity 中集成 Firebase 后无法在 Android 设备上运行
- python - 在 pandas 数据框中使用 bin
- redis - Redis集群无法添加节点
- selenium - Selenium 节点与网格断开连接