如何 Maybe-ify 这个递归代码?
How to Maybe-ify this recursive code?
我有这段 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
这很好用,但现在我想要 return 类型的 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]
恶作剧来重用代码,而是使用多态性在 [Double]
和 [[Double]]
层获得相同的 shape-checking 行为。同样更清楚的是,您已经涵盖了所有感兴趣的案例,因为您一次只处理一层 list-iness。
我有这段 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
这很好用,但现在我想要 return 类型的 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]
恶作剧来重用代码,而是使用多态性在 [Double]
和 [[Double]]
层获得相同的 shape-checking 行为。同样更清楚的是,您已经涵盖了所有感兴趣的案例,因为您一次只处理一层 list-iness。