[英]Get constraint in GADT-style declaration without specifically using constructor?
Consider the following: 考虑以下:
{-# 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
The constructor Test
is declared with an Ord
constraint. 构造函数
Test
用Ord
约束声明。 In comp
, I've specifically taken a parameter constructed with Test
, which gives the Ord
constraint allowing me to use <
在
comp
,我专门采用了Test
构造的参数,该参数给出了Ord
约束,使我可以使用<
Now, suppose I wanted to write: 现在,假设我想写:
comp' :: Test a -> Bool
comp' x = (first x) < (second x)
Using the projection functions to get the first and second element. 使用投影函数获取第一个和第二个元素。 This is not okay because my parameter
x
was not (necessarily) constructed with Test
, so there is no Ord
constraint. 这是不对的,因为我的参数
x
不是(必需)用Test
构造的,所以没有Ord
约束。
So, for my question, is there a way to take the parameter as just x
but still somehow have the Ord
constraint from the Test
constructor, without having to "unpack" or pattern match on the Test
constructor or add the constraint to my function? 所以,我的问题,是有办法把参数作为刚刚
x
,但仍不知何故有Ord
从约束Test
的构造,而不必“解压”或模式匹配的Test
构造函数或约束添加到我的功能?
As for why I would want this, I have a data type with a constructor taking many values, one of which I only need in this particular function, so unpacking it makes my function unnecessarily verbose: 至于为什么要这样,我有一个带有许多值的构造函数的数据类型,其中一个仅在此特定函数中需要,所以解压缩它会使我的函数不必要地冗长:
myFunction :: Thing -> ...
myFunction (Thing _ _ _ _ need _ _) ...
As opposed to 相对于
myFunction t = ... (need t)
You can define a function which extracts all of the constraints from the constructor: 您可以定义一个函数,该函数从构造函数中提取所有约束:
data Test a where
Test :: Ord a => { first :: a, second :: a } -> Test a
openTest :: Test a -> (Ord a => r) -> r
openTest Test{} x = x
You can then write 然后你可以写
comp :: Test a -> Bool
comp x = openTest x $ first x < second x
but note that the implementation of openTest
is completely trivial - and it is less typing to just inline the pattern matching: 但是请注意,
openTest
的实现是非常简单的-仅内联模式匹配就不需要键入代码了:
comp' :: Test a -> Bool
comp' x@Test{} = first x < second x
Note also this (ie the Test{}
syntax) will work with any constructor, even if it is not a record constructor. 还请注意,此方法(即
Test{}
语法)将适用于任何构造函数,即使它不是记录构造函数也是如此。 Your actual function can simply be expressed as 您的实际功能可以简单地表示为
myFunction t@Thing{} = ... (need t) ...
or equivalently 或同等
openThing :: Thing a -> (ThingConstraints a => r) -> r
openThing Thing{} x = x
myFunction t = ... (openThing $ need t) ...
Finally, you can also define a function to extract a specific field as well as the constraints which apply to this field, which can be very useful for large constructors with many constraints: 最后,您还可以定义一个函数以提取特定字段以及适用于该字段的约束,这对于具有许多约束的大型构造函数可能非常有用:
first' :: Test a -> (Ord a => a -> r) -> r
first' t@Test{} x = x (first t)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.