我有这个Haskell代码片段来计算最小二乘回归的成本函数:
cost :: [[Double]] -> [[Double]] -> Double cost [[]] [[]] = 0 cost ((x:xs):xss) ((y:ys):yss) = (x-y)^2 + cost [xs] [ys] + cost xss yss cost _ _ = 0 print (cost [[1,2,3],[4,5,6]] [[1,3,3],[4,6,6]]) -- 2.0
这很好,但现在我想要一个返回类型Maybe Double
.我怎么能这样做?让我们说最后一个案例cost _ _ = Nothing
.结果应该是Just 2.0
这里给出的输入.
为空列表添加一个案例,将所有递归调用转换为绑定,并应用于return
每个等式中的最终结果.从而:
cost :: [[Double]] -> [[Double]] -> Maybe Double cost [] [] = return 0 cost [[]] [[]] = return 0 cost ((x:xs):xss) ((y:ys):yss) = do c <- cost [xs] [ys] c' <- cost xss yss return ((x-y)^2 + c + c') cost _ _ = Nothing
但是,案件数量令我担忧.你可以考虑写这样的东西,而不是:
import Control.Applicative costBy :: (a -> a -> Maybe Double) -> [a] -> [a] -> Maybe Double costBy f [] [] = return 0 costBy f (x:xs) (y:ys) = liftA2 (+) (f x y) (costBy f xs ys) costBy _ _ _ = Nothing cost' :: [[Double]] -> [[Double]] -> Maybe Double cost' = costBy (costBy (\x y -> return ((x-y)^2)))
在这里,您不需要cost [xs] [ys]
shenanigans来重用代码,而是使用多态来在层[Double]
和[[Double]]
层上获得相同的形状检查行为.更清楚的是,您已经涵盖了所有感兴趣的案例,因为您一次只处理一层列表.