Haskell Stack Overflow - C

I just met Haskell, so I donโ€™t really know how to code in this language, and therefore, sorry if this is a duplicate, but I donโ€™t understand other code written in this language.

I am trying to write an algorithm that takes the sum of positive even numbers not exceeding a given value. I tried to write code, however I got a C error.

Here is my code:

sumint :: Int -> Int sumint x | x==0 = 0 | x==1 = 1 | (x `mod` 2 == 0) && (x >= 2) = x + (sumint x-2) | (x `mod` 2 /= 0) && (x >= 1) = x + (sumint x-1) 

Where am I mistaken to get this error?

+5
source share
2 answers

Initial error: infinite recursion

Code Execution:

 sumint :: Int -> Int 

Hey, signature type. You sway.

 sumint x | x==0 = 0 

The main body, cool.

  | x==1 = 1 

A completely unnecessary case. Well, of course ... except. 1 not even so, why do we include it in the amount? It must be zero (or completely removed).

  | (x `mod` 2 == 0) && (x >= 2) = x + (sumint x-2) 

The meat of the problem is here. 1. X is even - excellent. 2. X is positive, yep. Result: x + (sumint x) - 2 No!

  • Error 1: the notification function application binds the tiger than the operators, so it should be x + sumint (x-2) .

This is the reason. sumint 2 == 2 + (sumint 2) - 2 + (sumint 2) -2 + (sumint 2) -2 + ... , yay infinite recursion.

  | (x `mod` 2 /= 0) && (x >= 1) = x + (sumint x-1) 

Another case ...... positive ... but why are we adding x? You want to add evens, not odds. Therefore, correcting the above problem, we get:

  • Mistake 2: if you defined x oddly, do not add to x . Just use sumint (x-1) .

Then you have no business. What happens if x is not positive? You need a (other) case.

 | otherwise = 0 

Next issue: no accumulation

Now the problem is that you are creating a large chunk (an invaluable calculation) instead of working in a constant space, accumulating the result as you move. Please note, if we expand your calculations, say 6, we get:

 sumint 6 = 6 + sumint (6-2) = 6 + 4 + sumint (4-2) = 6 + 4 + 2 + sumint (2-2) = 6 + 4 + 2 + 0 

You really do not want all these add-ons to be separated, it would be nice to go to the drive, for example:

 sumint x = go x 0 where go n accumulator | n <= 0 = accumulator | odd n = go (n-1) accumulator | otherwise = go (n-2) (accumulator + n) 

Side note. Other residents of the stacks may mention that the battery is strict, which is a good shape. I do not want to distract the current seeker with this discussion here. Note that using -O2 optimization is enough.

Idiomatic solutions

All the above solutions are pretty verbose. The general operation, iterating through a list using a function and battery, is a fold type. Fold is one of many highly optimized structural workarounds common to functional programming. In this case, the "strict left fold" is a typical candidate (from Data.List ). That is, foldl' ' prime ( ' ) by convention means that it is strict, and l means left.

 sumint n = foldl' (+) 0 [val | val <- [0..n], even val] 

Here we turned off the list to get our amount. To create a list of interests, we used a list comprehension - first we list the values โ€‹โ€‹from 0..n and skip any value that does not match the even predicate.

We can further cleanse this and improve it using the sum function and understanding the list, which are executed by 2, which gives us only the ones you want:

 sumint n = sum [0,2..n] 
+12
source

His problem is with operator priority. In Haskell, the application application has the highest possible priority. Thus, when you write sumint x - 2 , although you interpret it as sumint (x-2) , Haskell interprets it as (sumint x) - 2 . So you are trying to define sumint x directly in terms of sumint x - which simply accumulates recursive function calls until the stack overflows. You need to add explicit brackets if you want the subtraction to be evaluated before the function application.

+10
source

Source: https://habr.com/ru/post/1236205/


All Articles