2017-09-09 105 views
2

我正在編寫一個類Separate,它在不同結構的「部分」上獨立執行某些操作;例如一個複數的真實和複雜的部分(後來我還需要它的列表)。通過這種方式,我可以編寫不關心他們正在執行的這些結構中的哪一個的函數,但會以這種獨立的方式執行。複雜對偶實例

這些功能應該在沒有零件的結構上正常工作,例如, Double。 (我知道有一個標準偏差定義爲複數,它給出了一個實數,但「獨立」一個在我的情況下更有意義)。

但我遇到了一些實例聲明的問題。在操作中尤其應該是「乘用Double」,又名scale

class Separate a where 
    scale :: Double -> a -> a 

instance Separate Double where 
    scale = (*) 

instance (Floating a) => Separate (Complex a) where 
    d `scale` z = (*d) <$> z 

當然這並不編譯,因爲*是不是一個Double和一般Floating a之間定義。但我不能直接定義instance Separate (Complex Double) where...

我可以只寫一個函數Double -> Complex Double -> Complex Double沒有類,但標準偏差必須分別爲不同的結構定義。

任何想法?

+2

只需使用FlexibleInstances。 –

回答

4

至於中午。指出,定義instance Separate (Complex Double)是完全正常的,如果您使用FlexibleInstances擴展名,這是一個流行和無害的擴展。

但也有其他的選擇,太多,例如:

instance (Floating a) => Separate (Complex a) where 
    d `scale` z = (* realToFrac d) <$> z 

而組成的實例the best kind of instance

instance (Separate a) => Separate (Complex a) where 
    d `scale` z = (d `scale`) <$> z 
+0

不錯!我喜歡最後的選擇。但爲什麼編譯器不會抱怨呢?它不知道規模是否定義爲一個給定的(例如Int)?如果你在稍後發生這種情況時使用它,它會不會complan?我應該仔細閱讀構成實例.. – jorgen

+1

@jorgen注意'(Separate a)=>'子句,它保證'a''爲'a'定義。這個例子說'Complex' *保留了*'Separate'的性質。 – luqui

+0

啊,有道理 – jorgen

2

這是一個類型的問題,而不是一個問題以及你如何處理實例。如您所說,(*)未在DoubleFloat之間定義。但是,我們可以輕鬆地在DoubleFloat之間進行轉換,所以您很幸運!使用realToFrac,我們可以在各種分數類型之間進行轉換。

如下我會改寫實例:

instance (Floating a) -> Separate (Complex a) where 
    d `scale` z = (* (realToFrac d)) <$> z