簡體   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