繁体   English   中英

在没有专门使用构造函数的情况下获得GADT样式声明中的约束?

[英]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

构造函数TestOrd约束声明。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM