Code review request?

Hey everyone, Let me know if this is not the right place for this, but I am curious if someone could take a look at my code and maybe share some feedback / how a more experienced haskeller would approach this problem. New to Haskell, pretty experienced with imperative languages. I have solved the following problem in Haskell:
Given a non-empty array, return true if there is a place to split the array so that the sum of the numbers on one side is equal to the sum of the numbers on the other side.
canBalance([1, 1, 1, 2, 1]) -> true canBalance([2, 1, 1, 2, 1]) -> false canBalance([10, 10]) -> true
Here is my code (my solution uses `can_split_even` not `canBalance`) ``` can_split_even :: (Num a) => (Eq a) => [a] -> Bool can_split_even xs = True `elem` is_even_at_each_spot where is_even_at_each_spot :: [Bool] is_even_at_each_spot = map (is_split xs) [1 .. (length xs - 1)] where is_split :: (Num a) => (Eq a) => [a] -> Int -> Bool is_split xs index = sum (take index xs) == sum (drop index xs) ``` Thanks so much! -- Jake Vossen Colorado School of Mines, Class of 2022 B.S. Computer Science PGP: 08CD 67DA FE3A 0AE7 B946 6AC3 B812 7052 D9E3 817B https://jake.vossen.dev

Hi, this is how I would have solved the exercise: canBalanceRec [] _ _ = False canBalanceRec (x:xs) s1 s2 = s1+x==s2-x || canBalanceRec xs (s1+x) (s2-x) canBalance xs = s==0 || canBalanceRec xs 0 s where s=sum xs Note that there is one difference: in this case canBalance [-2,-2,4] = True because I think I can split the list into [ ] and the rest (since the sum of the empty list is 0 and the same is the sum of the elements of the lists). Anyway this is a matter of how we interpret the text of the exercise (your function would return False instead). Note that removing the "s==0 ||" makes no difference. An advantage of my solution is that it is less expensive, since its computational complexity is linear in the length of the list xs. Yours uses sum and drop many times, and so is slower. Just to have an idea of the difference (using ghci interpreter):
canBalance [1..10000] False (*0.02* secs, 6,974,552 bytes) can_split_even [1..10000] False (*5.60* secs, 11,395,843,384 bytes)
Cheers,
Ut
Il giorno mer 15 gen 2020 alle ore 18:27 Jake Vossen
Hey everyone,
Let me know if this is not the right place for this, but I am curious if someone could take a look at my code and maybe share some feedback / how a more experienced haskeller would approach this problem.
New to Haskell, pretty experienced with imperative languages. I have solved the following problem in Haskell:
Given a non-empty array, return true if there is a place to split the array so that the sum of the numbers on one side is equal to the sum of the numbers on the other side.
canBalance([1, 1, 1, 2, 1]) -> true canBalance([2, 1, 1, 2, 1]) -> false canBalance([10, 10]) -> true
Here is my code (my solution uses `can_split_even` not `canBalance`)
``` can_split_even :: (Num a) => (Eq a) => [a] -> Bool can_split_even xs = True `elem` is_even_at_each_spot where is_even_at_each_spot :: [Bool] is_even_at_each_spot = map (is_split xs) [1 .. (length xs - 1)] where is_split :: (Num a) => (Eq a) => [a] -> Int -> Bool is_split xs index = sum (take index xs) == sum (drop index xs) ```
Thanks so much!
-- Jake Vossen Colorado School of Mines, Class of 2022 B.S. Computer Science PGP: 08CD 67DA FE3A 0AE7 B946 6AC3 B812 7052 D9E3 817B https://jake.vossen.dev
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Also worth noting that Ut's version can be expressed as a fold:
canBalanceElem x acc@(y, z, p) = if p then acc else let y'=y+x; z'=z-x in
(y', z', y'==z')
canBalanceFold xs = (\(_, _, p) -> p) $ foldr canBalanceElem (0, sum xs,
False) xs
On Wed, Jan 15, 2020 at 10:54 AM Ut Primum
Hi, this is how I would have solved the exercise:
canBalanceRec [] _ _ = False canBalanceRec (x:xs) s1 s2 = s1+x==s2-x || canBalanceRec xs (s1+x) (s2-x) canBalance xs = s==0 || canBalanceRec xs 0 s where s=sum xs
Note that there is one difference: in this case canBalance [-2,-2,4] = True because I think I can split the list into [ ] and the rest (since the sum of the empty list is 0 and the same is the sum of the elements of the lists). Anyway this is a matter of how we interpret the text of the exercise (your function would return False instead). Note that removing the "s==0 ||" makes no difference.
An advantage of my solution is that it is less expensive, since its computational complexity is linear in the length of the list xs. Yours uses sum and drop many times, and so is slower. Just to have an idea of the difference (using ghci interpreter):
canBalance [1..10000] False (*0.02* secs, 6,974,552 bytes) can_split_even [1..10000] False (*5.60* secs, 11,395,843,384 bytes)
Cheers, Ut
Il giorno mer 15 gen 2020 alle ore 18:27 Jake Vossen
ha scritto: Hey everyone,
Let me know if this is not the right place for this, but I am curious if someone could take a look at my code and maybe share some feedback / how a more experienced haskeller would approach this problem.
New to Haskell, pretty experienced with imperative languages. I have solved the following problem in Haskell:
Given a non-empty array, return true if there is a place to split the array so that the sum of the numbers on one side is equal to the sum of the numbers on the other side.
canBalance([1, 1, 1, 2, 1]) -> true canBalance([2, 1, 1, 2, 1]) -> false canBalance([10, 10]) -> true
Here is my code (my solution uses `can_split_even` not `canBalance`)
``` can_split_even :: (Num a) => (Eq a) => [a] -> Bool can_split_even xs = True `elem` is_even_at_each_spot where is_even_at_each_spot :: [Bool] is_even_at_each_spot = map (is_split xs) [1 .. (length xs - 1)] where is_split :: (Num a) => (Eq a) => [a] -> Int -> Bool is_split xs index = sum (take index xs) == sum (drop index xs) ```
Thanks so much!
-- Jake Vossen Colorado School of Mines, Class of 2022 B.S. Computer Science PGP: 08CD 67DA FE3A 0AE7 B946 6AC3 B812 7052 D9E3 817B https://jake.vossen.dev
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

For what it's worth, this is an equivalent one-liner:
canBalance xs = any ((== sum xs) . (*2)) (scanl (+) 0 xs)
On Wed, 15 Jan 2020 at 15:02, Akhra Gannon
Also worth noting that Ut's version can be expressed as a fold:
canBalanceElem x acc@(y, z, p) = if p then acc else let y'=y+x; z'=z-x in (y', z', y'==z') canBalanceFold xs = (\(_, _, p) -> p) $ foldr canBalanceElem (0, sum xs, False) xs
On Wed, Jan 15, 2020 at 10:54 AM Ut Primum
wrote: Hi, this is how I would have solved the exercise:
canBalanceRec [] _ _ = False canBalanceRec (x:xs) s1 s2 = s1+x==s2-x || canBalanceRec xs (s1+x) (s2-x) canBalance xs = s==0 || canBalanceRec xs 0 s where s=sum xs
Note that there is one difference: in this case canBalance [-2,-2,4] = True because I think I can split the list into [ ] and the rest (since the sum of the empty list is 0 and the same is the sum of the elements of the lists). Anyway this is a matter of how we interpret the text of the exercise (your function would return False instead). Note that removing the "s==0 ||" makes no difference.
An advantage of my solution is that it is less expensive, since its computational complexity is linear in the length of the list xs. Yours uses sum and drop many times, and so is slower. Just to have an idea of the difference (using ghci interpreter):
canBalance [1..10000] False (0.02 secs, 6,974,552 bytes) can_split_even [1..10000] False (5.60 secs, 11,395,843,384 bytes)
Cheers, Ut
Il giorno mer 15 gen 2020 alle ore 18:27 Jake Vossen
ha scritto: Hey everyone,
Let me know if this is not the right place for this, but I am curious if someone could take a look at my code and maybe share some feedback / how a more experienced haskeller would approach this problem.
New to Haskell, pretty experienced with imperative languages. I have solved the following problem in Haskell:
Given a non-empty array, return true if there is a place to split the array so that the sum of the numbers on one side is equal to the sum of the numbers on the other side.
canBalance([1, 1, 1, 2, 1]) -> true canBalance([2, 1, 1, 2, 1]) -> false canBalance([10, 10]) -> true
Here is my code (my solution uses `can_split_even` not `canBalance`)
``` can_split_even :: (Num a) => (Eq a) => [a] -> Bool can_split_even xs = True `elem` is_even_at_each_spot where is_even_at_each_spot :: [Bool] is_even_at_each_spot = map (is_split xs) [1 .. (length xs - 1)] where is_split :: (Num a) => (Eq a) => [a] -> Int -> Bool is_split xs index = sum (take index xs) == sum (drop index xs) ```
Thanks so much!
-- Jake Vossen Colorado School of Mines, Class of 2022 B.S. Computer Science PGP: 08CD 67DA FE3A 0AE7 B946 6AC3 B812 7052 D9E3 817B https://jake.vossen.dev
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (4)
-
Akhra Gannon
-
Jake Vossen
-
Julian Camilo Osorio
-
Ut Primum