What is the equivalent of this Python code in Hasekell?

Question:

I try to make the below Haskell code equal to the Python code, but it doesn’t work and i can’t spot the error? Can somebody spot the error? The Python output is what i want

def balanceList(lst):
    length = len(lst)
    if length<3:
        return lst
    else:
        middle=length//2
        return [lst[middle]] + balance(lst[middle+1:] + balance(lst[:middle]))

print( balanceList(list(range(1,10))) )
# [5, 3, 8, 2, 7, 4, 9, 6, 1]
balanceList :: [a] -> [a]
balanceList lst
  | len < 3 = lst
  | otherwise = [lst !! middle] ++ balanceList (drop (middle+1) lst) ++ balanceList (take (middle) lst) 
    where len = length lst; middle = len `div` 2

-- >>> balanceList [1..9]
-- [5,8,9,6,7,3,4,1,2]
Asked By: tturbo

||

Answers:

This is a problem with the parenthesis:

balanceList :: [a] -> [a]
balanceList lst
  | len < 3 = lst
  | otherwise = [lst !! middle] ++ balanceList (drop (middle+1) lst ++ balanceList (take (middle) lst))
    where len = length lst
          middle = len `div` 2

Here we thus balance the first part, append the last part and balance it again. But it is unclear if that was the intention in Python.

But using length is not very "Haskell-ish". You can split the list in three through recursion:

splitMiddle :: [a] -> ([a], a, [a])
splitMiddle ls = go ls ls
  where go [] (x:xs) = ([], x, xs)
        go [_] ~(x:xs) = ([], x, xs)
        go (_:_:ys) ~(x:xs) = let ~(b, m, a) = go ys xs in (x:b, m, a)

or with a NonEmpty:

import Data.List.NonEmpty(NonEmpty((:|)))

splitMiddle :: NonEmpty a -> ([a], a, [a])
splitMiddle (x :| xs) = go (x:xs) x xs
  where go [] x xs = ([], x, xs)
        go [_] x xs = ([], x, xs)
        go (_:_:ys) x ~(x1:xs) = let ~(b, m, a) = go ys x1 xs in (x:b, m, a)

Then we can use this to split and merge:

balanceList :: [a] -> [a]
balanceList lst@(_:_:_:_) = m : balanceList (a ++ balanceList b)
  where (b, m, a) = splitMiddle lst
balanceList lst = lst
Answered By: Willem Van Onsem
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.