ファンクションのタイプ定義を最も厳密にするか、最も緩いタイプにするのが一般的ですか?各アプローチの長所と短所は何ですか?私は、my pearson correlation codeを厳密に2倍書き換えてみると、書くこと、それに従うこと、そして理由をつけることがより簡単であることを発見しました(これはちょうど未熟なことかもしれません)。しかし、より広範な型定義を持つことが、関数をより一般的に適用可能にする方法を知ることもできます。より厳しい型定義は、技術的負債の一形態として特徴づけられるだろうか?ダブルスでファンクションタイプの制限
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)
時には、最も一般的な多形性のシグネチャは、あまりにも狂っています。制約リストだけが完全な特殊型よりも2倍長い場合は、これが本当に分かりやすいかどうか、それについて考えると思います。 ( 'ConstraintKind'-' type'defsはこのような署名をかなり読みやすくすることができますが、これはエラーメッセージなどではあいまいです。) – leftaroundabout