-1

I need to iterate through a list of integers and determine how many non zero elements there are and return those elements. I am not sure if I should use a counter variable as I iterate through the list, and I am interested in the most efficient way to iterate through the list itself. Here is what I have so far... i am new to haskell so I am writing some of this in pseudocode.

nonzero :: [int] -> Int
nonzero let counter = 0
if xs == 0 counter = counter + 1
Cooper Koenig
  • 37
  • 1
  • 2
  • 6
    The approach you are trying to use is suitable for an imperative language (e.g. JavaScript or C#), but it is not the right way to do this using Haskell. Do you know about recursion yet? If so, you should write this as a recursive function. If not, I _highly_ recommend that you should read about recursion before solving this problem. – bradrn Jan 29 '20 at 23:57
  • 1
    Check out [LYAH](http://learnyouahaskell.com/syntax-in-functions) for a quick primer on functions, including examples that iterate over lists to e.g. find their length or the sum of their elements – that other guy Jan 30 '20 at 00:55
  • 2
    Does this answer your question? [Counting number of elements in a list that satisfy the given predicate](https://stackoverflow.com/questions/9070570/counting-number-of-elements-in-a-list-that-satisfy-the-given-predicate) – Jin-oh Kang Jan 30 '20 at 03:10

2 Answers2

7

Preamble

You should pick up a tutorial or five on Haskell. Learning a language via stackoverflow questions is going to be slow and frustrating.

Comments

Type Signature and Type Variables

nonzero :: [int] -> Int

This is a type signature saying that nonzero is a function from a list of int to an value of type Int.

  • int with a lower-case i is a type variable and means the function works over lists of values of any type what-so-ever.

You probably wanted nonzero :: [Int] -> Int

Function declarations

nonzero let counter = 0

Nonzero is a function and should be declared as <function> <args...> = <expression>. So that would be:

nonzero xs = ...

Function body and immutability

The body of nonzero is an expression of type Int. In Haskell the variables are immutable. Saying counter = counter + 1 makes no more sense than it would in first grade math - your mental reaction should be "nuh-uh!". Instead think recursively in terms of base case and inductive step:

case xs of
   [] ->  -- Base case, what is the desired value when
          -- the list is empty?  `counter=0` right!
          0 -- In other words, nonzero [] ~ 0
    x:rest -> -- Inductive case.
              -- What do we do with an element?
              -- Compare with zero and...
         if x == 0
            then 1 + nonzero rest -- Add one to the answer
            else nonzero rest     -- Or don't add one if not

Progression

There are many different ways to write this function that get more or less fancy, more or less concise. Whenever you write a recursive function you're probably writing a form of fold or map over a list or other structure. Instead of manually looping over something there are lots of built-in functions to do this for you.

For example, determine if a value is a zero and emit a 1 if so or a 0 if not then sum the results:

nonzero xs = sum (map oneForZero xs)
oneForZero 0 = 1
oneForZero _anyOtherValue = 0

Notice the sum function is one of these "folds" over the list of Ints that is specifically performing addition. We could do this manually instead:

nonzero xs = foldr accumulate 0 xs
accumulate 0 acc = acc + 1
accumulate _ acc = acc + 0
Thomas M. DuBuisson
  • 64,245
  • 7
  • 109
  • 166
-1

countNonzeroes xs=sum[1|x<-xs,x/=0]

countNonzeroes xs=sum[1|x<-xs,x/=0]
main=print$countNonzeroes[0..9]

Try it online!

howMany=(length.).filter

howMany=(length.).filter
main=print$howMany(/=0)[0..9]

Try it online!

Roman Czyborra
  • 127
  • 1
  • 4