在 Haskell 中寫是絕對合法的
f :: () => Int -> Int
甚至
f :: (Num i, ()) => i -> i
為什么()允許這樣做?在我看來,它似乎沒有帶來任何資訊,但由于它是有效的語法,我想在某些情況下它會派上用場。
uj5u.com熱心網友回復:
空約束在產生約束的型別別名和型別族中很有用。例如,這是一個人為的例子。
type family F :: Type -> Constraint where
F (a -> b) = ()
F a = (Show a, Read a)
然后,foo :: F t => ...只需要Show和Read非函式型別。結合 GADTs / singletons,它可以被用來創建型別級別的機器。
可以撰寫一個簡單的約束來代替(), like Num Intor Bool ~ Bool,但是使用特殊的語法 like()可以更好地表達意圖。
uj5u.com熱心網友回復:
當您進入諸如ConstraintKindsand之類的擴展時TypeFamilies,可以計算約束,而不僅僅是靜態列出。
因此,有時界面要求您提供某種型別的東西Constraint,但您可能不需要任何實際約束。然后,您需要一種表示“空”約束的方法;沒有任何實際要求(并且在持有時也不會授予額外的權力),但仍然是一種東西Constraint。鑒于我們可以Constraint通過撰寫將多個約束組合成一個單一的專案(C1, C2, C3, ...),那么空約束的明顯語法是(). (與我們得到的“unit”語法完全相同(),可以解釋為“empty tuple”)
鑒于()kind 是有效的Constraint,你可以在任何Constraint需要 kind 的地方使用它。這包括作為型別簽名上的約束元組的一個成員,例如foo :: (EQ a, ()) => .... 它還包括所有約束,例如bar :: () => .... 這樣做沒有用,但很清楚這意味著什么,所有規則都適用于任何其他Constraint.
一般來說,您可以通過仔細思考規則以使它們的任何可能組合都有意義,然后盡可能嚴格地遵守它們,從而制作出一種易于理解的編程語言。試圖添加越來越多的特殊情況以排除對特定功能的“無用”使用是一項永無止境的任務,使使用系統的每個人都必須記住所有的特殊情況以及正常規則,遲早會有人被束縛想出一個你沒有想到的背景關系,實際上“無用”的東西畢竟不是無用的。在所有可以撰寫的“無用”代碼中,只有極小部分有希望被諸如“=>()”。所以一般來說,編程語言設計者需要一個很好的理由來禁止像空約束這樣的事情;詢問為什么經常允許這樣的事情只會得到無聊的答案:“為什么不呢?”
uj5u.com熱心網友回復:
您可以使用ConstraintKinds擴展來定義約束的別名,例如:
{-# LANGUAGE ConstraintKinds #-}
type Foo a = (Num a, Ord a)
myFun :: Foo a => a -> Bool
myFun = (0 <)
但因此,您將列出多少個約束本身是未知的。因此它接受任何元組的元組,因為約束的數量可以是零、一或更多。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/452946.html
