简体   繁体   English

使用文件夹在Haskell中定义函数

[英]Define function in Haskell using foldr

I'm trying to define a function in Haskell using the foldr function: 我正在尝试使用foldr函数在Haskell中定义一个函数:

    fromDigits :: [Int] -> Int

This function takes a list of Ints (each on ranging from 0 to 9) and converts to a single Int. 该函数获取一个Int列表(每个Int的范围从0到9)并转换为单个Int。 For example: 例如:

    fromDigits [0,1] = 10
    fromDigits [4,3,2,1] = 1234
    fromDigits [2,3,9] = 932
    fromDigits [2,3,9,0,1] = 10932

Anyway, I have no trouble defining this using explicit recursion or even using zipWith: 无论如何,我毫不费力地使用显式递归甚至使用zipWith定义了这一点:

    fromDigits n = sum (zipWith (*) n (map ((^)10) [0..]))

But now I have to define it using a foldr, but I don't know how to get the powers of 10. What I have is: 但是现在我必须使用文件夹来定义它,但是我不知道如何获得10的幂。

    fromDigits xs = foldr (\x acc -> (x*10^(???)) + acc) 0 xs

How can I get them to decrease? 如何减少它们? I know I can start with (length xs - 1) but what then? 我知道我可以从(length xs-1)开始,但是那又如何呢?

Best Regards 最好的祝福

The nice thing about foldr is that it's so extemely easy to visualise! 约的好处foldr的是,它是如此extemely容易想象!

foldr f init [a,b, ... z]
≡ foldr f init $ a : b : ... z : []
≡                a`f b`f`... z`f`init
≡ f a (f b ( ... (f z init)...)))

so as you see, the j -th list element is used in j consecutive calls of f . 如您所见,第j个列表元素用于f j个连续调用中。 The head element is merely passed once to the left of the function. head元素只传递一次到函数的左侧。 For you application, the head element is the last digit. 对于您的应用程序,head元素是最后一位数字。 How should that influence the outcome? 那应该如何影响结果? Well, it's just added to the result, isn't it? 好吧,它只是添加到结果中,不是吗?

15 = 10 + 5
623987236705839 = 623987236705830 + 9

– obvious. - 明显。 Then the question is, how do you take care for the other digits? 然后的问题是,您如何照顾其他数字? Well, to employ the above trick you first need to make sure there's a 0 in the last place of the carried subresult. 好吧,要使用上述技巧,您首先需要确保在携带的子结果的最后一位为0。 A 0 that does not come from the supplied digits! 来自提供的数字的0! How do you add such a zero? 您如何添加这样的零?

That should really be enough hint given now. 这实际上应该已经足够了。

You were almost there: 您几乎在那里:

your 你的

fromDigits xs = foldr (\\x acc -> (x*10^(???)) + acc) 0 xs fromDigits xs =文件夹(\\ x acc->(x * 10 ^(???))+ acc)0 xs

is the solution with 2 little changes: 有2个小更改的解决方案:

fromDigits = foldr (\\x acc -> acc*10 + x) 0 fromDigits =文件夹(\\ x acc-> acc * 10 + x)0

(BTW I left out the xs on each sides, that's not necessary. (顺便说一句,我在两边都省略了xs ,这不是必需的。

Another option would be 另一种选择是

fromDigits = foldl (\\x acc -> read $ (show x) ++ (show acc)) 0 fromDigits = foldl(\\ x acc->读$(显示x)++(显示acc))0

The trick is, you don't need to compute the power of 10 each time from scratch, you just need to compute it based on the previous power of ten (ie multiply by 10). 诀窍是,您不需要每次都从头开始计算10的幂,只需要根据以前的10的幂(即乘以10)来计算它。 Well, assuming you can reverse the input list. 好吧,假设您可以反转输入列表。

(But the lists you give above are already in reverse order, so arguably you should be able to re-reverse them and just say that your function takes a list of digits in the correct order. If not, then just divide by 10 instead of multiplying by 10.) (但是您在上面给出的列表已经是相反的顺序,因此可以说您应该能够将它们反向,并且只需说您的函数以正确的顺序获取数字列表即可。如果没有,则除以10而不是乘以10。)

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

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