[英]Get constraint in GADT-style declaration without specifically using constructor?
考虑以下:
{-# LANGUAGE GADTs, GADTSyntax #-}
data Test a where
Test :: Ord a => { first :: a, second :: a } -> Test a
comp :: Test a -> Bool
comp (Test fst snd) = fst < snd
构造函数Test
用Ord
约束声明。 在comp
,我专门采用了Test
构造的参数,该参数给出了Ord
约束,使我可以使用<
现在,假设我想写:
comp' :: Test a -> Bool
comp' x = (first x) < (second x)
使用投影函数获取第一个和第二个元素。 这是不对的,因为我的参数x
不是(必需)用Test
构造的,所以没有Ord
约束。
所以,我的问题,是有办法把参数作为刚刚x
,但仍不知何故有Ord
从约束Test
的构造,而不必“解压”或模式匹配的Test
构造函数或约束添加到我的功能?
至于为什么要这样,我有一个带有许多值的构造函数的数据类型,其中一个仅在此特定函数中需要,所以解压缩它会使我的函数不必要地冗长:
myFunction :: Thing -> ...
myFunction (Thing _ _ _ _ need _ _) ...
相对于
myFunction t = ... (need t)
您可以定义一个函数,该函数从构造函数中提取所有约束:
data Test a where
Test :: Ord a => { first :: a, second :: a } -> Test a
openTest :: Test a -> (Ord a => r) -> r
openTest Test{} x = x
然后你可以写
comp :: Test a -> Bool
comp x = openTest x $ first x < second x
但是请注意, openTest
的实现是非常简单的-仅内联模式匹配就不需要键入代码了:
comp' :: Test a -> Bool
comp' x@Test{} = first x < second x
还请注意,此方法(即Test{}
语法)将适用于任何构造函数,即使它不是记录构造函数也是如此。 您的实际功能可以简单地表示为
myFunction t@Thing{} = ... (need t) ...
或同等
openThing :: Thing a -> (ThingConstraints a => r) -> r
openThing Thing{} x = x
myFunction t = ... (openThing $ need t) ...
最后,您还可以定义一个函数以提取特定字段以及适用于该字段的约束,这对于具有许多约束的大型构造函数可能非常有用:
first' :: Test a -> (Ord a => a -> r) -> r
first' t@Test{} x = x (first t)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.