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