为什么在这个例子中天花板和地板操作员之间没有区别? (Haskell的)

时间:2013-11-28 03:47:10

标签: haskell

我必须将列表分成两半,从而产生列表前半部分和列表(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(halve []))的错误,解释器不知道数组是由什么组成的,但我怎么能这样做以使类型无关紧要?我希望那条线能给我([],[])。

1 个答案:

答案 0 :(得分:1)

您是否尝试过以下操作:

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函数向下舍入(下限)正商数并向上舍入(ceils)负商:

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分支。你的功能不必要地复杂。