我正在嘗試定義一個Complex資料型別,并且我希望建構式能夠將任何數字作為實體,所以我想使用泛型型別,只要它確實實作了一個Num實體
我之所以GADT這樣做,是因為據我了解,DataTypeContexts語言擴展是一種“錯誤功能”,即使我認為這在這種情況下會很有用......
無論如何,這是我的代碼:
data Complex where
Real :: ( Num num, Show num ) => num -> Complex
Imaginary :: ( Num num, Show num ) => num -> Complex
Complex :: ( Num num, Show num ) => num -> num -> Complex
real :: ( Num num, Show num ) => Complex -> num
real (Real r) = r
real (Imaginary _i ) = 0
real (Complex r _i ) = r
這里的real實作給出了以下錯誤:
Couldn't match expected type ‘num’ with actual type ‘num1’
‘num1’ is a rigid type variable bound by
a pattern with constructor:
Real :: forall num. (Num num, Show num) => num -> Complex,
in an equation for ‘real’
at <...>/Complex.hs:29:7-12
‘num’ is a rigid type variable bound by
the type signature for:
real :: forall num. (Num num, Show num) => Complex -> num
at <...>/Complex.hs:28:1-47
? In the expression: r
In an equation for ‘real’: real (Real r) = r
? Relevant bindings include
r :: num1
(bound at <...>/Complex.hs:29:12)
real :: Complex -> num
(bound at <...>/Complex.hs:29:1)
據我了解,這是由于回傳型別確實被解釋為不同......所以我嘗試洗掉型別定義并讓ghc他對型別施展魔法,但結果型別簽名是相同的......
誰能向我解釋這里有什么問題?
uj5u.com熱心網友回復:
Complex問題是,這些定義允許您在 (1) 構造值和 (2) 應用函式時選擇不同的型別real。這兩種情況之間沒有任何聯系,因此沒有什么可以強制它們之間的型別相同。例如:
c :: Complex
c = Real (42 :: Int)
d :: Double
d = real c
的定義d要求real函式回傳a Double,但里面沒有Double包裹c,只有Int。
至于解決辦法,有兩種可能:(1)在這兩點之間建立連接,強制型別相同,(2)允許里面的型別轉換為任何其他數值型別。
要在兩點之間建立型別級連接,我們需要使用在兩點都存在的型別。那會是什么型別的?很明顯,這就是c. 所以我們需要讓 type 以c某種方式傳達其中包含的內容:
data Complex num = Real num | Imaginary num | Complex num num
real :: Complex num -> num
real = ...
-- Usage:
c :: Complex Int
c = Real 42
d :: Int
d = real c
請注意,我實際上并不需要 GADT。
要允許型別轉換,您需要該型別需要另一個型別類num。該類Num有辦法從任何整數型別轉換,但沒有辦法轉換為任何此型別別,因為它沒有意義:3.1415 無法有意義地轉換為整數型別。
因此,您必須想出自己的轉換方式,并為所有允許的型別實作它:
class Convert a where
toNum :: Num n => a -> n
data Complex where
Real :: ( Num num, Show num, Convert num ) => num -> Complex
...
real :: Num num => Complex -> num
real (Real r) = toNum r
...
為了清楚起見,我認為第二種選擇非常瘋狂。我只是為了說明而提供它。不要這樣做。選擇選項 1。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/462813.html
