gpt4 book ai didi

haskell - 函数类型限制

转载 作者:行者123 更新时间:2023-12-01 09:16:43 25 4
gpt4 key购买 nike

通常最好对函数使用最严格或最宽松的类型定义?每种方法的优缺点是什么?我发现当我重写 my pearson correlation code 时使用严格的 double ,我更容易写作、遵循和推理(这可能只是缺乏经验)。但我也可以看到拥有更广泛的类型定义如何使函数更普遍适用。更严格的类型定义会被描述为一种技术债务吗?

使用类型类:

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)

double :

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)

最佳答案

可读性是一个见仁见智的问题。一般来说,我发现更通用的类型签名更具可读性,因为可能的定义更少(有时甚至只有一个不发散的定义)。例如,看到 mean 只有一个 Fractional 约束会立即限制在该函数中执行的操作(与 Double 版本相比,它可能是据我所知,执行 sqrt 操作)。当然,泛化类型is not always more readable . (And just for fun)

拥有更通用版本的函数的主要缺点是它们可能在运行时保持未优化,因此必须将 DoubleFloating 函数字典传递给mean 每次被调用。

您可以通过添加 SPECIALIZE pragma .这告诉编译器基本上复制您的函数代码并实例化一些类型变量。如果你知道你将几乎只使用 Double 来调用你的 mean 函数,那么这就是我要做的

{-# SPECIALIZE mean :: [Double] -> Double #-}
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)

您还可以在代码中看到签名的专用版本!耶!

关于haskell - 函数类型限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42377833/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com