[Haskell-beginners] length problem

Alex Hammel ahammel87 at gmail.com
Fri Feb 6 21:07:02 UTC 2015


`everyNth` applies a function f to every nth item in a list. If you want to
double every other item in a list you can do

everyNth 2 (*2) aList

In order to accomplish this, it makes an infinite list of functions where
every nth function is `f` (the user-supplied function) and the rest are
`id`. (This function terminates when applied to finite lists becase zipWith
stops when the shorter of it's arguments runs out). So:

everyNth 2 (*2) [1, 2, 3, 4]

is the same as

zipWith ($) [id, (*2), id, (*2)] [1, 2, 3, 4]

On Fri, Feb 6, 2015 at 12:52 PM, Roelof Wobben <r.wobben at home.nl> wrote:

> Alex Hammel schreef op 6-2-2015 om 20:41:
>
>> This is mostly for my own recreation, feel free to ignore it.
>>
>> Your solution is fine, but it lacks modularity. What if you discover that
>> you don't actually want to double every other number but triple it? Or if
>> the list of numbers is suddenly a list of words and you need to capitalize
>> every other one? You don't want to have to write a new function from
>> scratch. Let's make a function that applies any function to every other
>> value:
>>
>> everyOther :: (a -> a) -> [a] -> [a]
>> everyOther _ []       = []
>> everyOther _ [x]      = [x]
>> everyOther f (x:y:xs) = x : f y : everyOther f xs
>>
>> doubleEveryOther :: [Int] -> [Int]
>> doubleEveryOther = everyOther (*2)
>>
>> But hang on, what if the requirements change again and now we have to
>> double every third value? Writing something like this is no fun:
>>
>> everyThird :: (a -> a) -> [a] -> [a]
>> everyThird _ []         = []
>> everyThird _ [x]        = [x]
>> everyThird _ [x,y]      = [x,y]
>> everyThird f (x:y:z:xs) = x : y : f z : everyThird f xs
>>
>> And the implementation of everyHundredAndFifth will obviously be
>> ridiculous. Clearly what we need is an `everyNth` function which allows the
>> programmer to specify which list elements the function is applied to.
>>
>> One trick is to create a list of functions and use zipWith ($). ($) is
>> just function application; so a list with `id` at every position except the
>> nth will work:
>>
>> λ zipWith ($) [id, (+1), id, (+1)] [1, 2, 3, 4]
>> [1,3,3,5]
>>
>> We can use `cycle` to make an infinite list of functions and `replicate`
>> to generate the padding of the function list:
>>
>> everyNth :: Int -> (a -> a) -> [a] -> [a]
>> everyNth n f = zipWith ($) fs
>>   where
>>       fs = cycle $ replicate (n-1) id ++ [f] -- e.g. cycle [id, f] when n
>> is 2
>>
>>
> oke, Can you also explain what this function does exactly.
>
> I see a variable n and f and I see cycle en replicate and  a n-1
>
> What is I want to multiply the second item by 2.
> That was the challenge I had now.
>
> Roelof
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20150206/5c108750/attachment-0001.html>


More information about the Beginners mailing list