简体   繁体   English

列表理解递归[Haskell]

[英]List Comprehension to Recursion [Haskell]

I have the following function, which divides a list of Maybes with an Int input. 我有以下函数,该函数用Int输入划分Maybes列表。

divideList :: Int -> [Maybe Int] -> [Maybe Double]

ie

 divideList 100 [Just 5, Just 4, Nothing]   == [Just 20, Just 25.0, Nothing]

As a reminder the Maybe datatype is defined as follows: 提醒一下,Maybe数据类型定义如下:

 data Maybe a = Nothing | Just a

My code looks(and works) as followings: 我的代码看起来(并可以正常工作)如下:

divideList m xs = [ div2 x | x <- xs]
    where
        div2 (Just n) | n > 0   = Just (fromIntegral m / fromIntegral n)
        div2 _                  = Nothing

Now I'm trying to write the same function again, but this time just with recursion and without list comprehensions. 现在,我尝试再次编写相同的函数,但是这次只是使用递归而不使用列表推导。 However I can't seem to get it working. 但是我似乎无法正常工作。

Here's my (wrong) guess: 这是我的(错误的)猜测:

divideList m xs = div2  x 
    where
        div2 (Just x) | x > 0   = Just (fromIntegral m / fromIntegral x)
        div2 _                  = Nothing

You are almost there. 你快到了

  1. First define the division function separately 首先分别定义除法函数

     div3 :: Int -> Maybe Int -> Maybe Double div3 i (Just n) | n > 0 = Just (fromIntegral i / fromIntegral n) div3 i _ = Nothing 
  2. Then, for each item in the list, call the div3 and concatenate it with the result of the recursive call to divideList , like this 然后,对于列表中的每个项目,调用div3并将其与对divideList的递归调用的结果连接起来,如下所示

     divideList :: Int -> [Maybe Int] -> [Maybe Double] divideList _ [] = [] divideList m (x:xs) = (div3 mx):(divideList m xs) 

Here, 这里,

divideList _ [] = []

is called the base condition of your recursion. 称为递归的基本条件 That decides when your recursion ends. 这决定了您的递归何时结束。

What I always recommend is this: do not write direct recursive solutions like what you're trying to do. 我总是建议这样做:不要像您想做的那样编写直接的递归解决方案。 They're not idiomatic, they're harder to read, and they get pretty hard to write once you're doing anything complex. 它们不是惯用语言,它们更难阅读,一旦完成复杂的工作,它们就会变得很难编写。

Instead, figure out how to write your solution with standard library functions like map , filter and so on. 相反,请找出如何使用标准库函数(例如mapfilter等)编写解决方案的方法。 Then, as an exercise, write your own versions of those library functions. 然后,作为练习,编写您自己的那些库函数的版本。 In this case: 在这种情况下:

divideList m xs = map div2 xs
    where
        div2 (Just n) | n > 0   = Just (fromIntegral m / fromIntegral n)
        div2 _                  = Nothing

-- Apply the function `f` to each element of the list, returning a list of the results,
-- in the order of the corresponding arguments.
map f []     = _   -- Fill me in
map f (x:xs) = _   -- Fill me in

I'd suggest to write first a function for the division of two integral numbers. 我建议首先编写一个函数,将两个整数相除。 It must return a Maybe Double , as the calculation isn't always possible. 它必须返回Maybe Double ,因为计算并非总是可行的。

div2 m n = if n <= 0 then Nothing else Just (fromIntegral m / fromIntegral n)

Then you just need to apply this function to every element of the list, which can be done with map . 然后,您只需要将此函数应用于列表的每个元素即可,这可以通过map来完成。 However, as the number is "hidden" in a Maybe , you can use the function (>>=) to "unwrap" it (when it isn't a Nothing , which stays a Nothing , as we want). 然而,随着数量的“隐藏” Maybe ,你可以使用函数(>>=)以“解包”它(当它是不是Nothing ,它可以停留一个Nothing ,因为我们想要的)。

divideList m xs = map (>>= div2 m) xs

Or shorter: 或更短:

divideList m = map (>>= div2 m)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM