[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