From cgibbard at gmail.com Sat Jan 2 19:03:52 2010 From: cgibbard at gmail.com (Cale Gibbard) Date: Sat Jan 2 18:36:59 2010 Subject: nubBy, groupBy specification In-Reply-To: <18531661.1770691262457152299.JavaMail.nabble@isper.nabble.com> References: <18531661.1770691262457152299.JavaMail.nabble@isper.nabble.com> Message-ID: <89ca3d1f1001021603m122193fcm12d68be6ea3df270@mail.gmail.com> 2010/1/2 : > I'm inclined to agree with you. Could you please post the sources to both nubBy > and groupBy to see what has changed? > > Thanks, > Kim-Ee > yeoh@cs.wisc.edu Sure thing, Here is the report's implementation of nubBy: ------------------- nubBy :: (a -> a -> Bool) -> [a] -> [a] nubBy eq [] = [] nubBy eq (x:xs) = x : nubBy eq (filter (\y -> not (eq x y)) xs) ------------------- And here is the implementation in GHC 6.10.4 and GHC 6.12.1: ------------------- nubBy eq l = nubBy' l [] where nubBy' [] _ = [] nubBy' (y:ys) xs | elem_by eq y xs = nubBy' ys xs | otherwise = y : nubBy' ys (y:xs) -- Not exported: -- Note that we keep the call to `eq` with arguments in the -- same order as in the reference implementation -- 'xs' is the list of things we've seen so far, -- 'y' is the potential new element elem_by :: (a -> a -> Bool) -> a -> [a] -> Bool elem_by _ _ [] = False elem_by eq y (x:xs) = y `eq` x || elem_by eq y xs ------------------- Note that the comment is actually incorrect. The report implementation of nubBy applies the function such that earlier accepted elements of the list are the left parameter to eq. Simply switching the y `eq` x to become x `eq` y in elem_by produces something which passes QuickCheck tests at the very least. I believe it's really the right thing at that point. The implementation of groupBy in 6.10.4 and 6.12.1 is the same as the report version, and I'm happy with it: ------------------- groupBy :: (a -> a -> Bool) -> [a] -> [[a]] groupBy _ [] = [] groupBy eq (x:xs) = (x:ys) : groupBy eq zs where (ys,zs) = span (eq x) xs ------------------- My main concern with it is that the report says: ------------------- When the "By" function replaces an Eq context by a binary predicate, the predicate is assumed to define an equivalence ------------------- which I think is much too strong an assumption given that these functions have reasonably natural and quite useful extensions to non-equivalence relations, which the code provided by the Report actually implements. - Cale From sebf at informatik.uni-kiel.de Sat Jan 2 21:07:15 2010 From: sebf at informatik.uni-kiel.de (Sebastian Fischer) Date: Sat Jan 2 20:40:23 2010 Subject: nubBy, groupBy specification In-Reply-To: <89ca3d1f1001021603m122193fcm12d68be6ea3df270@mail.gmail.com> References: <18531661.1770691262457152299.JavaMail.nabble@isper.nabble.com> <89ca3d1f1001021603m122193fcm12d68be6ea3df270@mail.gmail.com> Message-ID: On Jan 3, 2010, at 1:03 AM, Cale Gibbard wrote: > nubBy' (y:ys) xs > | elem_by eq y xs = nubBy' ys xs I wonder why the author of this code did not use "any (eq y)" instead of "elem_by eq y" as "elem_by" is not exported anyway. Does "elem_by" compile to more efficient code? The version with "any" could be "fixed" (made equivalent to the report version) easily by using "any (`eq` y)". The comment on "elem_by" gives me the impression that the semantics of "nubBy" was changed by accident in the new version and I agree that it should be fixed. Or maybe the semantics was changed on purpose in order to annoy people that ignore the precondition that Cale proposes to relax (; +1 for the relaxation. Cheers, Sebastian -- Underestimating the novelty of the future is a time-honored tradition. (D.G.) From fw at deneb.enyo.de Sat Jan 23 04:50:40 2010 From: fw at deneb.enyo.de (Florian Weimer) Date: Sat Jan 23 04:22:47 2010 Subject: Unsafe hGetContents In-Reply-To: <4AD2E717.8070103@gmail.com> (Simon Marlow's message of "Mon, 12 Oct 2009 09:21:43 +0100") References: <877hvylk57.fsf@mid.deneb.enyo.de> <1253192223-sup-3700@peray> <87zl888fsh.fsf@mid.deneb.enyo.de> <4ACB3F1A.9090803@gmail.com> <1254835066-sup-8275@peray> <4ACB4B28.6080907@gmail.com> <87skdql4kd.fsf@mid.deneb.enyo.de> <4AD2E717.8070103@gmail.com> Message-ID: <87pr51cfpr.fsf@mid.deneb.enyo.de> * Simon Marlow: >> What about handles from System.Process? Do they count as well? > > Sure - we hopefully don't consider System.Process to be unsafe. Here's a demonstration that lazy input has an observable effect. It needs the Perl helper script included below. Of course, this example is constructed, but there are similar issues to consider when network IO is involved. For instance, not reading the lazy structure to its end causes the server to keep the connection open longer than necessary. ---------------------------------------------------------------------- -- Based on Oleg Kiselyov's example in: -- module Main where import System.IO (hGetContents) import System.Process (runInteractiveProcess) f1, f2:: String -> String -> String f1 e1 e2 = e1 `seq` e2 `seq` e1 f2 e1 e2 = e2 `seq` e1 `seq` e1 f = head . tail . lines spawn :: () -> IO String spawn () = do (inp,out,err,pid) <- runInteractiveProcess "perl" ["magic.pl"] Nothing Nothing hGetContents out main = do s1 <- spawn () s2 <- spawn () print $ f1 (f s1) (f s2) -- print $ f2 (f s1) (f s2) ---------------------------------------------------------------------- #!/usr/bin/perl # Magic program to demonstrate that lazy I/O leads to observable # differences in behavior. use strict; use warnings; use Fcntl ':flock'; open my $self, '<', $0 or die "opening $0: $!\n"; # use this file as lock flock($self, LOCK_SH) or die "flock(LOCK_SH): $!\n"; print "x" x 100_000 . "\n"; # blocks if reader blocks print flock($self, LOCK_EX | LOCK_NB) ? "locked\n" : "failed\n"; # only succeeds if the other process has exited