Reputation: 9360
I am trying to extract from a list only elements at odd positions.I know there are specific methods in Data.List but i am new and am trying to learn by reinventing the wheel.
So far i have tried this approach where i am branching the inner method
manF::[Int]->[Int]
manF []=[]
manF ls=go ls [] 0 where
go [] nl _ = nl
go (x:xs) rez cnt=if cnt `mod`2 ==0 then go xs (x:rez) (cnt+1) else go xs rez (cnt+1)
But i would have to reverse this result at the end.
Is there anything more atomic then using maybe for dealing with null's
So if i move the if clause on the left side of the cons
operator what can i return instead of null? I have tried Nothing,[] with no sucess.
manF::[Int]->[Int]
manF []=[]
manF ls=go ls [] 0 where
go [] nl _ = nl
go (x:xs) rez cnt=if cnt `mod`2 ==0 then x else *(something?!)* : go xs rez (cnt+1)
Upvotes: 2
Views: 156
Reputation: 477200
But i would have to reverse this result at the end.
If you work with an accumulator, the way you do here, yes you have to reverse the result. This also results in a problem in case you are processing an "infinite list", since in that case the recursion will never terminate, and you thus get stuck into an infinite loop (until you run out of memory).
So if i move the if clause on the left side of the cons operator what can i return instead of null?
There is not really something like null
(well there is undefined
, but we would add that value to the head), nor will Nothing
do the trick, since that is a data constructor for the Maybe
type. You can use the empty list in case you want to terminate the sequence, but you can not fill in some "empty" in the head.
But in fact you do not need an inner method, nor do you need to coun the indices. You can use pattern matching for this:
manF :: [a] -> [a]
manF (x:_:xs) = x : manF xs
manF [x] = [x]
manF [] = []
Note that here the pattern is (x:_:xs)
which is a compact form of (x:(_:xs))
, so here we thus match a "cons" with x
as head, and the tail should be a "cons" as well with as head _
(a value we do not care about), and as tail xs
. By doing so, we developed a means to make hops of two when iterating over the list.
The other clauses are base cases: for a singleton list we return that singleton list, and for the empty list, we return the empty list. We can merge the last two into one clause like:
manF :: [a] -> [a]
manF (x:_:xs) = x : manF xs
manF l = l
Note that due to lazyness, if we process an "infinite list", the algorithm will not get stuck into an infinite loop (of course given the generator of the source list does not go into an infinite loop), and we can thus use this to process "streams".
Another advantage is that our integer can never run into overflow (although for even-odd checks that would not make a difference, for a slightly different function, like for instance yield every third element, this could result in problems).
Upvotes: 7
Reputation: 531808
Try mutual recursion. The standard demonstration of this is implementing odd
and even
in terms of each other:
odd, even :: Int -> Bool
odd 0 = False
odd n = not (even (n - 1))
even 0 = True
even n = not (odd (n - 1))
For manF
, you might write
manF :: [Int] -> [Int]
manF = go_odd where
go_odd [] = []
go_odd (x:xs) = x : go_even xs
go_even [] = []
go_even (x:xs) = go_odd xs
Upvotes: 6