我將在這里使用 C 作為示例來展示我所追求的。對于復數算術,它同時具有復數和虛數型別:
https://en.cppreference.com/w/c/language/arithmetic_types#Imaginary_floating_types
例如,它們具有將兩個數字與 double imaginary 型別相乘將具有 double 型別的屬性。這與使用實部為 0.0 但不完全相同的復數幾乎但不完全相同。虛構型別不顯式存盤自動消除不需要的計算和存盤 0.0。
此外,它可以防止帶符號零的一些問題。例如,如果 a 和 b 為負數,則 (0.0 i*a)*(0.0 i*b) 的計算結果為 (-a*bi*0.0),否則為 (-a*b i*0.0)。如果將結果輸入到帶有分支切割的函式中,這可能會令人驚訝。一個虛構的型別避免了這種不需要的零否定。
我的問題是你能否在 Haskell 中定義一個類似的虛構型別(除了一個復雜型別)以及它的操作( )、(-)、(*)和(/),這樣它們的行為就像在 C 中一樣?似乎至少對于 Num 和 Fractional 類的當前定義是不可能的,因為 ( )、(-)、(*) 和 (/) 具有 -> a -> a 作為型別簽名,因此例如乘以兩個結果,虛數不能有不同的型別。但是,是否可以對這些類進行不同的定義,以便我所追求的成為可能?
我問這個不是出于實際目的。我只是想更好地理解 Haskell 的型別系統的能力。
uj5u.com熱心網友回復:
是的,當然你可以定義這樣的型別。您將無法使用該Num界面進行所有操作;但是您可以自由定義其他型別的任何其他功能,如果需要,甚至可以將它們設為中綴運算子。
這是一個型別的示例,它在型別級別跟蹤它是虛數還是實數,并支持具有替代名稱的加法和乘法(減法和除法不需要此處未顯示的任何新想法):
{-# Language DataKinds #-}
{-# Language KindSignatures #-}
{-# Language TypeFamilies #-}
-- hide the Mindful data constructor
module Mindful (Mindful, real, iTimes, ( .), (*.), EqBool, KnownReality(isReal)) where
newtype Mindful (reality :: Bool) a = Mindful a deriving (Eq, Ord, Read, Show)
real :: a -> Mindful True a
real = Mindful
iTimes :: a -> Mindful False a
iTimes = Mindful
( .) :: Num a => Mindful r a -> Mindful r a -> Mindful r a
Mindful x . Mindful y = Mindful (x y)
(*.) :: (KnownReality r, KnownReality r', Num a)
=> Mindful r a -> Mindful r' a -> Mindful (EqBool r r') a
xm@(Mindful x) *. ym@(Mindful y) = Mindful (iSquared * x * y) where
iSquared = if isReal xm || isReal ym then 1 else -1
type family EqBool a b where
EqBool False False = True
EqBool False True = False
EqBool True False = False
EqBool True True = True
class KnownReality r where isReal :: Mindful r a -> Bool
instance KnownReality False where isReal _ = False
instance KnownReality True where isReal _ = True
如果您出于某種原因必須準確地使用名稱 等(我不推薦這樣做,這將是一個很大的痛苦),您可以看看我關于控制命名空間的另一個答案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/474027.html
