GHC 9.2.4 給出了以下代碼的多重宣告錯誤:
data X = A | B | C
data Y = A | B | C
現在 GHC 有很多新的擴展。是否有一個允許我執行上述操作(因為它在語意上適合我的問題域),或者是否仍然是通用解決方案的前綴,比如data X = XA | XB | XC?
uj5u.com熱心網友回復:
即使沒有任何擴展,您也可以在不同的模塊中宣告這兩種型別。您在評論中說“我希望這些東西可以命名空間”;模塊系統是命名空間。
module X where
data X = A | B | C
module Y where
data Y = A | B | C
module OnlyUsesX where
import X
foo :: Char -> Maybe X
foo 'a' = Just A
foo 'b' = Just B
foo 'c' = Just C
foo _ = Nothing
module UsesBoth where
import X (X) -- import only the type name unqualified, since
-- it's unambiguous
import qualified X as X -- also import the entire module qualified, for
-- the ambiguous stuff
import Y (Y)
import qualified Y as Y -- the "as Y" is pointless here, but normally the
-- full module name is longer; if you use the type
-- name as the module alias, then it looks like you
-- have a namespace associated with the type, much
-- like OO code
foo :: X -> Y -> String
foo X.A Y.A = "both A"
foo X.B Y.B = "both B"
foo _ _ = "I can't be bothered enumerating the rest of the possibilities"
如果您將您的型別放在專用于該一種型別的小模塊中,那么在您使用多種型別的其他模塊中,您可以將這些型別簡單地稱為Xor Y,并將該型別的建構式/欄位稱為X.whatever
or Y.whatever。
這使您可以在建構式/欄位名稱本身中使用短的無前綴名稱(如果您關心的話,可以避免前綴感染派生的 read/show/json/etc 實體)。在沒有使用沖突名稱的情況下,您可以選擇匯入不合格的前綴并洗掉前綴,如果前綴被烘焙到實際的建構式/欄位名稱中,您將不會有。它還避免了假設的 GHC 版本在允許同一命名空間中的重復建構式/模式名稱并嘗試使用型別來決議哪個是哪個時必然會出現的任何歧義推理問題;如果你曾經在同一個命名空間中使用過沖突的匯入名稱,編譯器會告訴你,你可以只使用模塊前綴來解決它,以便雙方都受益編譯器和任何人類讀者。
uj5u.com熱心網友回復:
您應該為它們添加前綴,或將它們放在單獨的模塊中。并且您可能還應該以這種明確限定的方式使用它們。
但是,如果你堅持,你可以通過使用型別類并在其上構造模式同義詞來偽造多型的建構式以適用于這兩種情況。在這種情況下,最簡單的方法是利用這兩個同構于 的事實X:
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
class HasABCConstructors w where
fromX :: X -> w
toX :: w -> X
instance HasABCConstructors X where
fromX = id
toX = id
instance HasABCConstructors Y where
fromX XA = YA
fromX XB = YB
fromX XC = YC
toX YA = XA
toX YB = XB
toX YC = XC
pattern A :: HasABCConstructors w => w
pattern A <- (toX -> XA)
where A = fromX XA
ghci> A :: X
XA
ghci> A :: Y
YA
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/536664.html
標籤:哈斯克尔
