为什么在此示例中天花板和地板操作员之间没有区别?(哈斯克尔)



我必须将列表一分为二,得到列表前半部分和列表后半部分的元组(half1, half2)。当这个列表的长度是奇数时,那么我想使half1包含比half2更多的元素。

 halve :: [a] -> ([a],[a])
 halve [] = ([],[])
 halve xs =
    if (((length(xs) `mod` 2)==1))
    then(take (ceiling(toRational(length(xs) `div` 2))) xs, drop(ceiling(toRational(length(xs) `div` 2))) xs)
    else ((take (floor(toRational(length(xs) `div` 2))) xs, drop (floor(toRational(length(xs) `div` 2))) xs))
 main = do
 putStrLn(show (halve [1,2,3])) gives me [1],[2,3] instead of [1,2],[3]
 putStrLn(show (halve [])) gives me an error

这让我认为在mod操作或天花板操作中存在一些截断。我知道,对于putStrLn(show(half-[]))的错误,解释器不知道数组是由什么组成的,但我如何才能使它与类型无关?我希望这行给我([],[])。

您尝试过以下操作吗:

halve :: [a] -> ([a], [a])
halve xs = let n = div (length xs + 1) 2
           in (take n xs, drop n xs)
-- or alternatively
halve :: [a] -> ([a], [a])
halve xs = splitAt (div (length xs + 1) 2) xs

div函数向下取整(楼层)正商,向上取整(天花板)负商:

div  5 2 =>  2
div -5 2 => -2
div  6 2 =>  3
div -6 2 => -3

halve函数的工作方式正如您所期望的:

halve []     => ([], [])
halve [1..5] => ([1,2,3], [4,5])
halve [1..6] => ([1,2,3], [4,5,6])

我不明白你为什么需要if then else分支。你的职能过于复杂。

最新更新