一般情況下,最好是對某個函數使用最嚴格或最寬鬆的類型定義嗎?每種方法的優缺點是什麼?我發現當我使用嚴格雙打重寫my pearson correlation code時,我更容易寫出,跟隨和推理(這可能只是缺乏經驗)。但是我也可以看到,如果有更廣泛的類型定義會使這些功能更普遍適用。更嚴格的類型定義是否被視爲技術債務的一種形式?功能類型限制
隨着類型類:
import Data.List
mean :: Fractional a => [a] -> a
mean xs = s/n
where
(s , n) = foldl' k (0,0) xs
k (s, n) x = s `seq` n `seq` (s + x, n + 1)
covariance :: Fractional a => [a] -> [a] -> a
covariance xs ys = mean productXY
where
productXY = zipWith (*) [x - mx | x <- xs] [y - my | y <- ys]
mx = mean xs
my = mean ys
stddev :: Floating a => [a] -> a
stddev xs = sqrt (covariance xs xs)
pearson :: RealFloat a => [a] -> [a] -> a
pearson x y = fifthRound $ covariance x y/(stddev x * stddev y)
pearsonMatrix :: RealFloat a => [[a]] -> [[a]]
pearsonMatrix (x:xs) = [pearson x y | y <- x:xs]:(pearsonMatrix xs)
pearsonMatrix [] = []
fifthRound :: RealFrac a => a -> a
fifthRound x = (/100000) $ fromIntegral $ round (x * 100000)
隨着雙打:
import Data.List
mean :: [Double] -> Double
mean xs = s/n
where
(s , n) = foldl' k (0,0) xs
k (s, n) x = s `seq` n `seq` (s + x, n + 1)
covariance :: [Double] -> [Double] -> Double
covariance xs ys = mean productXY
where
productXY = zipWith (*) [x - mx | x <- xs] [y - my | y <- ys]
mx = mean xs
my = mean ys
stddev :: [Double] -> Double
stddev xs = sqrt (covariance xs xs)
pearson :: [Double] -> [Double] -> Double
pearson x y = fifthRound (covariance x y/(stddev x * stddev y))
pearsonMatrix :: [[Double]] -> [[Double]]
pearsonMatrix (x:xs) = [pearson x y | y <- x:xs]:(pearsonMatrix xs)
pearsonMatrix [] = []
fifthRound :: Double -> Double
fifthRound x = (/100000) $ fromIntegral $ round (x * 100000)
沒錯,雖然有時候最普遍的多態簽名只是有點太瘋狂了。如果單獨的約束列表比完整的專用類型長兩倍,我會考慮它是否真的合理。 (雖然'ConstraintKind'''type'defs可以使這樣的簽名更具可讀性,但是這在錯誤信息等方面的代價是晦澀難懂的。) – leftaroundabout