用 Maybe 递归

Recursion with Maybe

我很难尝试编写一个函数来使用递归查找两个列表的总和,如果任何列表为空,则可能为 Nothing。

以下函数的数学运算是:

Σw[i]x[i]

其中 w 和 x 是等长的 int 数组

这是我的工作代码:

example :: [Int] -> [Int] -> Int
example [] [] = 0
example (x:xs) (l:ls) = ((x*l) + (example xs ls))

这是我想要工作的想法:

example :: [Int] -> [Int] -> Maybe Int
example [] [] = Nothing
example (x:xs) (l:ls) = Just((x*l) + (example xs ls))

谢谢

你很接近,但是你对 example xs ls returns a Maybe Int 的递归调用不能添加 IntMaybe Int(在 x*l + example xs ls 中),因此你在最后一行的错误。

你可以用fromMaybe来处理这种情况,使用0作为默认和:

example :: [Int] -> [Int] -> Maybe Int
example [] []         = Nothing
example (x:xs) (l:ls) = Just $ x * l + fromMaybe 0 (example xs ls)

或者(更简洁),您可以使用如下方式避免显式递归:

example [] [] = Nothing
example xl yl = Just $ sum $ zipWith (*) xl yl

请注意,您的模式匹配中有非详尽模式。两个不同长度的列表将导致模式匹配异常。

我猜你的意图是什么,不确定我是否理解正确:当两个输入列表长度不同时,你希望函数产生 Nothing

"happy" 基本情况是 0 就像第一次尝试一样,但提升到 Maybe

example [] [] = Just 0

要处理列表长度不同的情况,请包括只有 一个 列表为空的情况。对于不包括这些情况的非详尽模式匹配,您应该已经收到编译器警告。

example [] _ = Nothing
example _ [] = Nothing

那么,最后一种情况是您有两个非空列表。它看起来很像你第一次尝试的那一行,除了不是直接将加法应用于 example xs ys,我们 fmapexample xs ys 上加法,利用 MaybeFunctor.

这一事实
example (x : xs) (y : ys) = fmap (x * y +) (example xs ys)

用法示例:

λ> example [1,2] [3,4]
Just 11

λ> example [1,2] [3,4,5]
Nothing

顺便说一下,如果你想使用这个库,safe 将它变成单行代码是一个不错的选择。

import Safe.Exact

example xs ys = fmap sum (zipWithExactMay (*) xs ys)