splitAt implementation (using foldr) and infinite lists

Hi all. If i implement take using foldr take' :: Int -> [a] -> [a] take' n = foldr (\x z -> if fst x <= n then snd x : z else []) [] . zip [1..] it'll work fine with infinite lists. But if i implement splitAt similarly splitAt' :: Int -> [a] -> ([a], [a]) splitAt' n = foldr (\x (z1, z2) -> if fst x <= n then (snd x : z1, z2) else ([], snd x : z2)) ([], []) . zip [1..] and call it like this *Main> fst $ splitAt' 4 [1..] ^CInterrupted. it will hang. I don't understand, why it tries to compute second list (z2), if it only needs first?

On Mon, Apr 16, 2012 at 12:52:02PM +0400, Dmitriy Matrosov wrote:
Hi all.
If i implement take using foldr
take' :: Int -> [a] -> [a] take' n = foldr (\x z -> if fst x <= n then snd x : z else []) [] . zip [1..]
it'll work fine with infinite lists. But if i implement splitAt similarly
splitAt' :: Int -> [a] -> ([a], [a]) splitAt' n = foldr (\x (z1, z2) -> if fst x <= n then (snd x : z1, z2) else ([], snd x : z2)) ([], []) . zip [1..]
and call it like this
*Main> fst $ splitAt' 4 [1..] ^CInterrupted.
Try something like this: splitAt' n = foldr (\x zs -> if fst x <= n then (snd x : fst zs, snd zs) else ([], snd x : snd zs)) ([], []) . zip [1..] I'm no Haskell expert, but I suspect that when pattern-matching z2, it tries to evaluate it and it hangs... My version does not hang... hth, L. -- Lorenzo Bolla http://lbolla.info

You can also use lazy pattern matching.
http://en.wikibooks.org/wiki/Haskell/Laziness#Lazy_pattern_matching
On 16 April 2012 15:21, Lorenzo Bolla
splitAt' :: Int -> [a] -> ([a], [a]) splitAt' n = foldr (\x ~(z1, z2) -> if fst x <= n then (snd x : z1, z2) else ([], snd x : z2)) ([], []) . zip [1..]
Ozgur

On 04/16/12 18:21, Lorenzo Bolla wrote:
Try something like this: splitAt' n = foldr (\x zs -> if fst x<= n then (snd x : fst zs, snd zs) else ([], snd x : snd zs)) ([], []) . zip [1..]
I'm no Haskell expert, but I suspect that when pattern-matching z2, it tries to evaluate it and it hangs...
My version does not hang...
hth, L.
Thanks, Lorenzo! It works now. On 04/16/12 18:55, Ozgur Akgun wrote:
You can also use lazy pattern matching.
http://en.wikibooks.org/wiki/Haskell/Laziness#Lazy_pattern_matching
On 16 April 2012 15:21, Lorenzo Bolla
mailto:lbolla@gmail.com> wrote: > splitAt' :: Int -> [a] -> ([a], [a]) > splitAt' n = foldr (\x ~(z1, z2) -> if fst x <= n then (snd x : z1, z2) > else ([], snd x : z2)) > ([], []) > . zip [1..]
Ozgur Thanks, Ozgur!
participants (3)
-
Dmitriy Matrosov
-
Lorenzo Bolla
-
Ozgur Akgun