Haskell - 改组不同类型的列表?

时间:2017-09-02 16:58:28

标签: haskell

我是Haskell的新手,几天前我开始学习Haskell的课程。在这门课程中,有一项作业或作业,我现在仍然坚持。我会很感激我的问题的提示和解释,而不是完整的,彻底的答案,因为这是家庭作业,因此我不想因为另一项工作而受到赞扬。

分配是编写一个混洗函数(skyffla)。实际的改组不是我需要帮助理解的,而是算法应该通过的测试之一。我将算法用括号标记到洗牌部分,以表示它不太重要。

skyffla通过取第一个元素,第三个元素,第五个元素等等进行混洗,直到获取所有奇数索引,然后将它们附加到列表中。

此后,第一个列表中的其余元素应使用相同的方法处理,并附加到首次处理的列表中。然后继续,直到只剩下一个元素,然后最后将其附加到列表中。

如果我输入:

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

它会给我:

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]_

这正是我的代码所做的,实际的改组工作正如预期的那样。但正如我所提到的,有一个测试我无法通过我当前的实现。)

因此,其中一项测试是天幕应采取:[3.4, 2.3, 5, 185, 23]并返回:_[3.4, 5, 23, 2.3, 185]_

使用我的代码,我得到:_[3.4, 5.0, 23.0, 2.3, 185.0]_

这是正确的,除了" .0"附加到 5 185, 23

为什么会这样?

我怎样才能这样做" 5.0"例如,将被列为" 5"?

我的代码如下:

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 个答案:

答案 0 :(得分:4)

答案是你的代码是正确的。

当列表到达您的函数时,所有元素都已经是相同的类型

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

因为Haskell中的所有列表从一开始就是同类的。 (此处5被解释为fromInteger 5,将其转换为其上下文中所需的任何类型)

如果您将输出作为字符串进行比较,那么您将遇到此问题。如果您将它们作为数字列表进行测试,那么这不是问题。

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

所以你真正面临的是显示问题。克里斯马丁建议Data.Decimal,这是一种方法。我的观点是你没有问题,你的代码是正确的,而且是你需要改变的测试用例的处理。

答案 1 :(得分:0)

听起来你想要使用Decimal类型。

λ> import Data.Decimal

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