[Haskell-beginners] length problem

YCH dontdieych at gmail.com
Fri Feb 6 19:54:00 UTC 2015


Thanks for explanation.
2015. 2. 7. 오전 4:42에 "Alex Hammel" <ahammel87 at gmail.com>님이 작성:

> 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
>
> everyOther' :: (a -> a) -> [a] -> [a]
> everyOther' = everyNth 2
>
> everyThird' :: (a -> a) -> [a] -> [a]
> everyThird' = everyNth 3
>
> As for testing whether the length is odd or even: why not just reverse it,
> double every other number, and reverse it again?
>
> doubleEveryOther :: Num a => [a] -> [a]
> doubleEveryOther = reverse . everyOther (*2) . reverse
>
> Cheers,
> Alex
>
>
> On Fri, Feb 6, 2015 at 8:55 AM, Roelof Wobben <r.wobben at home.nl> wrote:
>
>> Oke,
>>
>> I have solved it already.
>> The problem was that I did list.length but Haskell uses length list
>>
>> Still too much Ruby in my system :(
>>
>> Roelof
>>
>>
>>
>> Francesco Ariis schreef op 6-2-2015 om 17:50:
>>
>>> (off-list) please consider not using html in your mails, it's quite
>>> difficult
>>> to read them for us who plaintext-friendly client
>>>
>>> On Fri, Feb 06, 2015 at 05:47:24PM +0100, Roelof Wobben wrote:
>>>
>>>> <html>
>>>>    <head>
>>>>
>>>>      <meta http-equiv="content-type" content="text/html;
>>>> charset=windows-1252">
>>>>    </head>
>>>>    <body bgcolor="#FFFFFF" text="#000000">
>>>>      Hello, <br>
>>>>      <br>
>>>>      I have to double every second element from the right. <br>
>>>>      <br>
>>>>      So for a even length array that means : 1 , 3 , 5 and so on <br>
>>>>      and for a non even lenght that means the 2,4 and so on. <br>
>>>>      <br>
>>>>      So I thought I could solve that on this way : <br>
>>>>      <br>
>>>>      -- | Doubles every second number from the right.<br>
>>>>      doubleEveryOther :: [Integer] -> [Integer]<br>
>>>>      doubleEveryOther []         = []     <br>
>>>>      doubleEveryOther (x:[])     = [x]   <br>
>>>>      doubleEveryOther (x:(y:zs)) <br>
>>>>         | ((x:(y:zs)).length) `mod` 2 /= 0 = [x] ++ (y * 2) :
>>>>      doubleEveryOther zs<br>
>>>>         | otherwise = [x *2]  ++ y : doubleEveryOther zs<br>
>>>>      <br>
>>>>      <br>
>>>>      <br>
>>>>      but this does not work because I see this error message : <br>
>>>>      <br>
>>>>      <div class="ide-error-span">src/Main.hs at 14:8-14:16 </div>
>>>>      <div class="ide-error-msg"><span>Couldn't match expected type ‘Int
>>>>          -> c0’ with actual type </span>
>>>>        <div class="CodeMirror cm-s-default" style="font-size:
>>>> 14px;">[<span
>>>>            class="cm-variable-2">Integer</span>]</div>
>>>>        <span title="Click to show/hide extra information"
>>>>          class="ide-error-collapse-btn"> …</span><span style="display:
>>>>          inline;">
>>>>          In the first argument of ‘(.)’, namely ‘(x : (y : zs))’
>>>>          In the first argument of ‘mod’, namely ‘((x : (y : zs)) .
>>>>          length)’
>>>>          In the first argument of ‘(/=)’, namely ‘((x : (y : zs)) .
>>>>          length) `mod` 2’<br>
>>>>          <br>
>>>>          <br>
>>>>          Can anyone give me a better way to check if I have a even or
>>>> odd
>>>>          length array ?<br>
>>>>          <br>
>>>>          Roelof<br>
>>>>          <br>
>>>>        </span></div>
>>>>      <br>
>>>>    </body>
>>>> </html>
>>>> _______________________________________________
>>>> Beginners mailing list
>>>> Beginners at haskell.org
>>>> http://www.haskell.org/mailman/listinfo/beginners
>>>>
>>>
>>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>
>
> _______________________________________________
> 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/20150207/b164fedd/attachment.html>


More information about the Beginners mailing list