4
votes

I am very new to Haskell, I started learning Haskell some days ago for a course that I have. In this course there is an assignment, or homework, that I am stuck with at the moment. I would appreciate hints and explanations to my problem more than full, outright answers, since this is homework, and as such I do not want to take credit for another's work.

The assignment is to write a shuffling function (skyffla). The actual shuffling is not what I need help understanding, but rather one of the tests that the algorithm should pass. I'll mark the algorithm to the shuffling section with parentheses as to denote it as less important.

(skyffla shuffles by taking the first element, the third element, the fifth element and so on, until all the odd indices were taken, and then append these to a list.

The remaining elements in the first list should thereafter be processed by the same method, and appended onto the list that was first processed. And on, and on, until there is only one element left, which is then lastly appended onto the list.

If I for example input:

skyffla [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

it will give me:

1: _[1, 3, 5, 7, 9, 11] ++ skyffla ([2, 4, 6, 8, 10, 12])_
2: _[1, 3, 5, 7, 9, 11] ++ [2, 6, 10] ++ skyffla ([4, 8, 12])_
3: _[1, 3, 5, 7, 9, 11, 2, 6, 10] ++ [4, 12] ++ skyffla([8])_ 
(4): _[1, 3, 5, 7, 9, 11, 2, 6, 10, 4, 12, 8]_

This is exactly what my code does, and the actual shuffling is working just as it is intended. But as I mentioned, there is one test that I can't pass with my current implementation.)

So, one of the tests is that skyffla should take: [3.4, 2.3, 5, 185, 23] and return: _[3.4, 5, 23, 2.3, 185]_.

With the code that I have, I get: _[3.4, 5.0, 23.0, 2.3, 185.0]_

This is correct except for the ".0" that is appended unto 5, 185, and 23.

Why is this?

How can I make it so that "5.0" for instance instead would be listed as "5"?

My code looks as follows:

skyffla :: [a] -> [a]
skyffla [] = []
skyffla xs
    | length xs == 1 = xs
    | otherwise = dropUnevenElements xs ++ skyffla newList  where
    newList = takeUnevenElements xs

dropUnevenElements :: [a] -> [a]
dropUnevenElements [] = []
dropUnevenElements (x:y:xs) = x:dropUnevenElements xs
dropUnevenElements x = x


takeUnevenElements :: [a] -> [a]
takeUnevenElements [] = []
takeUnevenElements (x:y:xs) = y:takeUnevenElements xs 
takeUnevenElements x = []
2
dropUnevenElements x = x? - Willem Van Onsem
And lists can only contain one type of elements. - Willem Van Onsem
Is 'skyffla' some weird phonetic translation of 'shuffle'? It should really be something like 'blanda'. - SwiftsNamesake
You can't have list whose elements are of different types. How is the test expressed? - Euge
The question title doesn't really reflect the content. Also, unless the output is validated as a string (which sounds like a terrible idea), the .0 won't matter at all. It's possible that whoever wrote the sample output simply didn't think about how show works for most floating-point types in Haskell. - SwiftsNamesake

2 Answers

4
votes

The answer is that your code is correct.

By the time the list reaches your function, all the elements are already the same type

ghci> [3.4, 2.3, 5, 185, 23]
[3.4,2.3,5.0,185.0,23.0]

because all lists in Haskell are homogeneous from the get-go. (Here 5 is interpreted as fromInteger 5, which casts it to whatever type is needed in its context)

If you are comparing the output as a string, then you will have this problem. If you are testing them as lists of numbers, it's not a problem.

ghci> skyffla [3.4, 2.3, 5, 185, 23] == [3.4, 5, 23, 2.3, 185]
True

So what you are really facing is a display problem. Chris Martin suggests Data.Decimal, which is one approach. My perspective is that you don't have a problem, your code is correct, and it's your handling of test cases that needs to change.

0
votes

It sounds like you want to be using a Decimal type.

λ> import Data.Decimal

λ> [3.4, 5, 23, 2.3, 185] :: [Decimal]
[3.4,5,23,2.3,185]