HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Taking change - convergent iteration through iterate

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
convergentiterateiterationthroughchangetaking

Problem

For the Code Review community challenge "Implement StackSTV", the algorithm requires a "convergent iterative scheme" to calculate the keep ratios of candidates that have been elected.

To simplify the calculation of those keep ratios I have written following function to truncate an infinite list that calculates the keep ratio scheme's next step.

I wonder whether I missed some basic library function and whether the function is idiomatic haskell:

{-
    Take items from a list, as long as the last item taken is not the same as the next item in the list.
    Passing an empty list returns an empty list.
-}
takeModified :: Eq a => [a] -> [a]
takeModified (x:xs) = [x] ++ go x xs
    where
    go :: Eq a => a -> [a] -> [a]
    go elem (x':xs')
       | elem == x' = []
       | otherwise  = [x'] ++ go x' xs'
    go elem [] = []
takeModified [] = []

Solution


  • Typically, where clauses don't include full type annotations, though this is mostly a matter of personal preference.



  • For prepending items to a list, prefer x:xs over [x] ++ xs.



  • In your "base case" of the recursive go function: go elem [] = [], elem is not used. Prefer _ in this case.



  • Your comment exceeds 80 characters in width. Again, a matter of personal preference. The note about passing an empty list returns an empty list is probably not necessary as this is very clearly the case from the code itself.



Here is how I would write this function:

takeWhileNotDup :: Eq a => [a] -> [a]
takeWhileNotDup [] = []
takeWhileNotDup (x:xs) = x:go x xs
  where
    go _ [] = []
    go previous (x:xs)
      | previous /= x = x:go x xs
      | otherwise = []

Code Snippets

takeWhileNotDup :: Eq a => [a] -> [a]
takeWhileNotDup [] = []
takeWhileNotDup (x:xs) = x:go x xs
  where
    go _ [] = []
    go previous (x:xs)
      | previous /= x = x:go x xs
      | otherwise = []

Context

StackExchange Code Review Q#153776, answer score: 2

Revisions (0)

No revisions yet.