【问题标题】:Recursion with Maybe使用 Maybe 进行递归
【发布时间】:2017-12-27 07:29:37
【问题描述】:

我很难尝试编写一个函数来使用递归查找两个列表的总和,如果任何列表为空,则可能是 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))

谢谢

【问题讨论】:

    标签: haskell recursion immutability


    【解决方案1】:

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

    “快乐”的基本情况是0,就像第一次尝试一样,但提升为Maybe

    example [] [] = Just 0
    

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

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

    那么,最后一种情况是您有两个非空列表。它看起来很像你第一次尝试的那条线,除了直接将加法应用到example xs ys,我们fmapexample xs ys上加法,利用@987654331这一事实@ 是 Functor

    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)
    

    【讨论】:

    • 为什么在第一个示例中得到 Just 11 而不是 Just 10?
    • @Soldalma 因为它正在计算 (1*3)+(2*4)。
    • 好的,知道了。在某些情况下,我仍然不熟悉 Haskell 的语法。
    【解决方案2】:

    您已经接近了,但是您对example xs ls 的递归调用返回了Maybe Int,并且您无法添加IntMaybe Int(在x*l + example xs ls 中),因此您最后的错误行。

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

    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,因为它最终会到达空列表案例。
    猜你喜欢
    • 2011-06-04
    • 2018-11-02
    • 2015-02-02
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多