当使用存在类型时,我们必须使用模式匹配语法来提取forall
编辑值。我们不能将普通的记录选择器用作函数。 GHC 报告错误并建议使用与此定义的模式匹配yALL
:
{-# LANGUAGE ExistentialQuantification #-}
data ALL = forall a. Show a => ALL { theA :: a }
-- data ok
xALL :: ALL -> String
xALL (ALL a) = show a
-- pattern matching ok
-- ABOVE: heaven
-- BELOW: hell
yALL :: ALL -> String
yALL all = show $ theA all
-- record selector failed
forall.hs:11:19:
Cannot use record selector `theA' as a function due to escaped type variables
Probable fix: use pattern-matching syntax instead
In the second argument of `($)', namely `theA all'
In the expression: show $ theA all
In an equation for `yALL': yALL all = show $ theA all
我的一些数据包含超过 5 个元素。如果我很难维护代码
使用模式匹配:
func1 (BigData _ _ _ _ elemx _ _) = func2 elemx
有没有一种好的方法可以使这样的代码可维护或将其包装起来以便我可以使用某种选择器?
存在类型比常规类型以更复杂的方式工作。 GHC(正确地)禁止您使用theA
作为一个函数。但想象一下没有这样的禁令。该函数的类型是什么?它必须是这样的:
-- Not a real type signature!
theA :: ALL -> t -- for a fresh type t on each use of theA; t is an instance of Show
非常粗暴地说,forall
使 GHC“忘记”构造函数参数的类型;类型系统只知道该类型是以下类型的实例Show
。因此,当您尝试提取构造函数参数的值时,无法恢复原始类型。
GHC 在幕后所做的就是上面对假类型签名的注释所说的——每次你与ALL
构造函数中,绑定到构造函数值的变量被分配一个唯一的类型,保证与其他类型不同。以这段代码为例:
case ALL "foo" of
ALL x -> show x
变量x
获取一个与程序中的所有其他类型不同的唯一类型,并且不能与任何类型变量匹配。这些独特的类型不允许逃逸到顶层——这就是为什么theA
不能用作函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)