Nyb*_*ble 28 haskell record existential-type
使用存在类型时,我们必须使用模式匹配语法来提取foralled值.我们不能将普通记录选择器用作函数.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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
我的一些数据需要超过5个元素.如果我使用模式匹配,很难维护代码:
func1 (BigData _ _ _ _ elemx _ _) = func2 elemx
Run Code Online (Sandbox Code Playgroud)
是否有一个很好的方法可以使代码像可维护或包装起来,以便我可以使用某种选择器?
Lui*_*las 19
存在类型比常规类型更精细地工作.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
Run Code Online (Sandbox Code Playgroud)
非常粗略地说,forall让GHC"忘记"构造函数参数的类型; 类型系统知道的所有类型都是这个类型的实例Show.因此,当您尝试提取构造函数参数的值时,无法恢复原始类型.
GHC在幕后所做的是对上面虚假类型签名的评论 - 每次你对ALL构造函数进行模式匹配时,绑定到构造函数值的变量被赋予一个唯一的类型,保证与其他类型不同.以此代码为例:
case ALL "foo" of
ALL x -> show x
Run Code Online (Sandbox Code Playgroud)
变量x获得一个独特的类型,该类型与程序中的每个其他类型都不同,并且不能与任何类型变量匹配.这些唯一类型不允许转移到顶层 - 这就是为什么theA不能用作函数的原因.
Dan*_*her 17
您可以在模式匹配中使用记录语法,
func1 BigData{ someField = elemx } = func2 elemx
Run Code Online (Sandbox Code Playgroud)
适用于大型类型的工作并且少得多.