From alex at alexjacobson.com Wed Aug 1 00:34:23 2007 From: alex at alexjacobson.com (Alex Jacobson) Date: Wed Aug 1 00:27:05 2007 Subject: [Haskell-cafe] Re: HDBC or HSQL In-Reply-To: <470880360707300831s44170261lb5d2002d1f56e70b@mail.gmail.com> References: <470880360707300831s44170261lb5d2002d1f56e70b@mail.gmail.com> Message-ID: <46B00D4F.6090206@alexjacobson.com> Out of curiosity, can I ask what you are actually trying to do? I am asking because I am trying to make HAppS a reasonable replacement for all contexts in which you would otherwise use an external relational database except those in which an external SQL database is a specific requirement. -Alex- Isto Aho wrote: > Hi, > > I was also wandering between these different db-libs and thanks for your > information. > > I tried several (HDBC, HSQL, HaskellDB) and made only small trials. > HaskellDB has quite many examples on wiki that gave a quick start to > further trials. > But, I wasn't able to tell that some of the fields have default values > and then it > was already time to move on to the HSQL and HDBC trials. > > Is it possible to use sql-array-types with HDBC with postgresql? I don't > remember was this the > reason why I eventually tried HSQL - anyhow, it was rather difficult to > get started with HDBC > but the src test cases helped here. One example in a wiki would do > miracles :) > > HSQL didn't have the array-types but it took only couple of hours to add > "a sort of" support > for those. There are some problems though... (indexed table queries > returning some nulls > is not yet working and ghci seems to be allergic to this) I was even > wondering, should I propose > a patch in some near future for this. > > But if HDBC can handle those sql-arrays or if you can give a couple of > hints, how to proceed > in order to add them there, given your view below, I'd be willing to try > to help / to try to use HDBC. > > br, > Isto > > 2007/7/30, John Goerzen >: > > On 2007-07-25, George Moschovitis > wrote: > > I am a Haskell newbie and I would like to hear your suggestions > regarding a > > Database conectivity library: > > > > HSQL or HDBC ? > > > > which one is better / more actively supported? > > I am the author of HDBC, so take this for what you will. > > There were several things that bugged me about HSQL, if memory serves: > > 1) It segfaulted periodically, at least with PostgreSQL > > 2) It had memory leaks > > 3) It couldn't read the result set incrementally. That means that if > you have a 2GB result set, you better have 8GB of RAM to hold it. > > 4) It couldn't reference colums in the result set by position, only by > name > > 5) It didn't support pre-compiled queries (replacable parameters) > > 6) Its transaction handling didn't permit enough flexibility > > I initially looked at fixing HSQL, but decided it would be easier to > actually write my own interface from scratch. > > HDBC is patterned loosely after Perl's DBI, with a few thoughts from > Java's JDBC, Python's DB-API, and HSQL mixed in. > > I believe it has fixed all of the above issues. The HDBC backends that > I've written (Sqlite3, PostgreSQL, and ODBC) all use Haskell's C memory > management tools, which *should* ensure that there is no memory > leakage. > > I use it for production purposes in various applications at work, > connecting to both Free and proprietary databases. I also use it in my > personal projects. hpodder, for instance, stores podcast > information in > a Sqlite3 database accessed via HDBC. I have found HDBC+Sqlite3 to be a > particularly potent combination for a number of smaller projects. > > http://software.complete.org/hdbc/wiki/HdbcUsers > has a list of some > programs that are known to use HDBC. Feel free to add yours to it. > > -- John > > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > > > > > -- > br, > Isto > > > ------------------------------------------------------------------------ > > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe From drtomc at gmail.com Wed Aug 1 01:44:32 2007 From: drtomc at gmail.com (Thomas Conway) Date: Wed Aug 1 01:36:54 2007 Subject: [Haskell-cafe] Backpatching Message-ID: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> Hi All, One of the things I've been working on lately is some ASN.1 stuff.One of the first things I wrote in Haskell was an ASN.1 parser. It only worked for a subset, and I'm revisiting it to make it handle a larger subset. One of the things that gets messy is that in lots of places you can put either a thing or a reference to a thing (i.e. the name of a thing defined elsewhere). For example, consider the production: NamedNumber ::= identifier "(" SignedNumber ")" | identifier "(" DefinedValue ")" If we ignore the second alternative, the natural translation into a Parsec parser would look like: namedNumber = do name <- identifier val <- parens signedNumber return (name, val) Now to handle the second alternative is easy enough: namedNumber = do name <- identifier val <- parens (fmap Left signedNumber <|> fmap Right definedValue) return (name, val) however because names can be used before they are defined the result typegoes from being type NamedNumber = (Name,Integer) to type NamedNumber = (Name,Either Integer Name) Nothing too terrible so far. The messiness comes in when you considerthe number of places that you have to replace a type 't' with (Either t Name). I'd really like to avoid having to do this. If I were using Prolog, I could finesse the problem by introducing afree variable and filling it in when I come across the definition[*]. Logic variable backpatching. :-) So one possibility would be to return a closure: ... return $ \bindings -> (name,resolve val bindings) resolve :: (Either t Name) -> Map Name t -> t or something like that. Then when you get to the end, you apply the bindings and voila, out pops the simple type. I'm not sure this will work quite as well as it sounds. This sounds like a common problem type. Is there a well known solution to this sort of problem? cheers, Tom [*] And then at the end use var/1 to look for undefined names. Urk. Actually, if I were using Prolog in the way most Prolog programmers use it, I wouldn't be thinking about the types. -- Dr Thomas Conway drtomc@gmail.com Silence is the perfectest herald of joy: I were but little happy, if I could say how much. From alex at alexjacobson.com Wed Aug 1 01:45:56 2007 From: alex at alexjacobson.com (Alex Jacobson) Date: Wed Aug 1 01:38:34 2007 Subject: [Haskell-cafe] OS swapping and haskell data structures Message-ID: <46B01E14.2020109@alexjacobson.com> If you create a Data.Map or Data.Set larger than fits in physical memory, will OS level swapping enable your app to behave reasonably or will things just die catastrophically as you hit a memory limit? -Alex- From bulat.ziganshin at gmail.com Wed Aug 1 01:45:01 2007 From: bulat.ziganshin at gmail.com (Bulat Ziganshin) Date: Wed Aug 1 01:39:47 2007 Subject: [Haskell-cafe] i need wxHaskell compiled for ghc 6.6.1 on Windows In-Reply-To: References: <20070720120236.CC2543244FF@www.haskell.org> <20070721052930.GA5934@dewdrop.local> <943563891.20070722180350@gmail.com> <4a0b969d0707220720v644de98es2122a0455ffa1e20@mail.gmail.com> <1806526956.20070725171858@gmail.com> Message-ID: <1234735448.20070801094501@gmail.com> Hello shelarcy, Wednesday, August 1, 2007, 4:03:52 AM, you wrote: >> problems. the only question that remains - does this version supports >> unicode? > Yes. Current darcs repository version support only unicode > enabled version. great, it's all what i need. but i'm still curious about other features enabled when building this package. can i see config.gcc or build.cfg or setup.h or any other file that shows feature list? also it will be useful to include such file with the next builds of wxHaskell -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com From stefanor at cox.net Wed Aug 1 01:59:01 2007 From: stefanor at cox.net (Stefan O'Rear) Date: Wed Aug 1 01:51:27 2007 Subject: [Haskell-cafe] OS swapping and haskell data structures In-Reply-To: <46B01E14.2020109@alexjacobson.com> References: <46B01E14.2020109@alexjacobson.com> Message-ID: <20070801055901.GA6033@localhost.localdomain> On Tue, Jul 31, 2007 at 10:45:56PM -0700, Alex Jacobson wrote: > If you create a Data.Map or Data.Set larger than fits in physical memory, > will OS level swapping enable your app to behave reasonably or will things > just die catastrophically as you hit a memory limit? Data.{Set,Map} uses balanced binary trees. So if you have a 1 billion element data set which is so large that no significant fraction of it fits into cache, you can expect to access a random element in ~9 seeks, which is less than a second... good enough? This is a lot worse than it could be because memory access is too transparent. When GHC triggers a page fault, the Right Thing to do is for Linux to somehow put *that haskell thread* to sleep; but instead it will put the entire capability (or your whole program on the non-threading rts) to sleep. Linux's filesystems (which use various kinds of trees internally) avoid this issue by using asynchronous IO requests, but that's not an option for VM since there's only so much room for callbacks in a MOV instruction! There is much fertile territory for OS design space exploration here! Stefan -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070731/7ad34934/attachment.bin From stefanor at cox.net Wed Aug 1 02:04:18 2007 From: stefanor at cox.net (Stefan O'Rear) Date: Wed Aug 1 01:56:43 2007 Subject: [Haskell-cafe] Backpatching In-Reply-To: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> References: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> Message-ID: <20070801060418.GB6033@localhost.localdomain> On Wed, Aug 01, 2007 at 03:44:32PM +1000, Thomas Conway wrote: > This sounds like a common problem type. Is there a well known solution > to this sort of problem? Mmm... logic programming? http://citeseer.ist.psu.edu/claessen00typed.html You'll only need the code for logic-variables, and even that can be simplified because your "terms" are non-recursive. (Even in the recursive case, a logic program like a HM typechecker usually only needs ~50 lines of prelude). (If you want an less enlightening answer, Map String (STRef s (Maybe Integer))).. Stefan -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070731/4548103b/attachment-0001.bin From derek.a.elkins at gmail.com Wed Aug 1 02:40:51 2007 From: derek.a.elkins at gmail.com (Derek Elkins) Date: Wed Aug 1 02:33:19 2007 Subject: [Haskell-cafe] Backpatching In-Reply-To: <20070801060418.GB6033@localhost.localdomain> References: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> <20070801060418.GB6033@localhost.localdomain> Message-ID: <1185950451.6796.1.camel@derek-laptop> On Tue, 2007-07-31 at 23:04 -0700, Stefan O'Rear wrote: > On Wed, Aug 01, 2007 at 03:44:32PM +1000, Thomas Conway wrote: > > This sounds like a common problem type. Is there a well known solution > > to this sort of problem? > > Mmm... logic programming? > > http://citeseer.ist.psu.edu/claessen00typed.html > > You'll only need the code for logic-variables, and even that can be > simplified because your "terms" are non-recursive. (Even in the > recursive case, a logic program like a HM typechecker usually only needs > ~50 lines of prelude). If someone is interested, I did transcribe and mildly generalize the code from that paper. From kaveh.shahbazian at gmail.com Wed Aug 1 03:02:11 2007 From: kaveh.shahbazian at gmail.com (Kaveh Shahbazian) Date: Wed Aug 1 02:54:33 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer Message-ID: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> This is about to put a definition/description to test. So please cooperate! ;) Is this a useful ? sufficient, not complete ? definition/description for a monad; for an imperative mind: (?) "A monad is like a loop that can run a new function against it's variable in each iteration." (I insist on the simplicity! And I will resist any expansion of this sentence (except for an exceptional note that I think of it hardly). I think there is not any complete definitions in computer world. At least there are many things to know when you want to use them in practice. So please have this in mind and review me!) Cheers :) -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/1bb8bff3/attachment.htm From bulat.ziganshin at gmail.com Wed Aug 1 03:59:57 2007 From: bulat.ziganshin at gmail.com (Bulat Ziganshin) Date: Wed Aug 1 03:54:37 2007 Subject: [Haskell-cafe] Re: HDBC or HSQL In-Reply-To: <46B00D4F.6090206@alexjacobson.com> References: <470880360707300831s44170261lb5d2002d1f56e70b@mail.gmail.com> <46B00D4F.6090206@alexjacobson.com> Message-ID: <1449382301.20070801115957@gmail.com> Hello Alex, Wednesday, August 1, 2007, 8:34:23 AM, you wrote: > I am asking because I am trying to make HAppS a reasonable replacement > for all contexts in which you would otherwise use an external relational > database except those in which an external SQL database is a specific > requirement. where i can read about such usage? -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com From dry.green.tea at gmail.com Wed Aug 1 04:16:50 2007 From: dry.green.tea at gmail.com (Alexis Hazell) Date: Wed Aug 1 04:09:17 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> References: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> Message-ID: <200708011816.51278.dry.green.tea@gmail.com> On Wednesday 01 August 2007 17:02, Kaveh Shahbazian wrote: > This is about to put a definition/description to test. So please cooperate! > ;) > Is this a useful ? sufficient, not complete ? definition/description for a > monad; for an imperative mind: (?) > > "A monad is like a loop that can run a new function against it's variable > in each iteration." At least in the context of Haskell, that's not correct. For a recent discussion about a simple definition of Haskell monads, see the thread beginning at: http://permalink.gmane.org/gmane.comp.lang.haskell.cafe/25882 Alexis. From haskell at list.mightyreason.com Wed Aug 1 04:44:08 2007 From: haskell at list.mightyreason.com (ChrisK) Date: Wed Aug 1 04:36:41 2007 Subject: [Haskell-cafe] Re: [Haskell] View patterns in GHC: Request?for?feedback In-Reply-To: <20070731230417.GA4866@localhost.localdomain> References: <20070723090900.GA25820@cs.cmu.edu> <46A87C01.5020808@list.mightyreason.com> <200707270902.50113.jcast@ou.edu> <20070727175124.GB12477@darcs.net> <20070731223153.GD12386@darcs.net> <20070731230417.GA4866@localhost.localdomain> Message-ID: Discussion continues below quoted text... Stefan O'Rear wrote: > On Tue, Jul 31, 2007 at 03:31:54PM -0700, David Roundy wrote: >> On Mon, Jul 30, 2007 at 11:47:46AM +0100, Jon Fairbairn wrote: >>> ChrisK writes: >>> >>>> And the readability is destroyed because you cannot do any type inference in >>>> your head. >>>> >>>> If you see >>>> >>>> { >>>> Matrix m = ....; >>>> Matrix x = m * y; >>>> ...; >>>> } >>>> >>>> Then you know very little about the possible types of y >>>> since can only conclude that: >>> [snippage] This is all very horrid, but as far as I can tell >>> what I was proposing wouldn't lead to such a mess, except >>> possibly via defaulting, which, as the least important >>> aspect of the idea could easily be abandoned. >> What your suggestion would do would be to make the type inferred for every >> pattern-matched function polymorphic, which means that in order to >> determine the correctness of a function you'd need to examine all other >> modules. Similarly, if you fail to include a type signature in some simple >> pattern-matched function in a where clause, adding an import of another >> module could make that function fail to compile (with an undeterminable >> type error). > > Excuse me? One of the most critical properties of type classes is that > adding new instances can never make old code that uses old instances > stop compiling; the worst you could get is a definition conflict. > > Stefan That is true, and it is one of of the perfect things about type classes. But that is not the problem with some of the proposals to make normal syntax patterns always look for a View inference. The problem is that to read any pattern match I have to know which View instance was chosen. So each and every pattern match requires me to run a type checker in my head which draws on all the View instances which were implicitly imported into the current module. That adding another invisible instance does not break the code is irrelevant, the problem is that huge amount of effort it takes the human reader to prove to herself or himself that any particular pattern match has been correctly understood. It should require a new syntax to invoke this complexity. -- Chris From haskell at list.mightyreason.com Wed Aug 1 05:32:01 2007 From: haskell at list.mightyreason.com (ChrisK) Date: Wed Aug 1 05:25:06 2007 Subject: [Haskell-cafe] Re: Backpatching In-Reply-To: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> References: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> Message-ID: Thomas Conway wrote: > One of the things that gets messy is that in lots of places you can > put either a thing or a reference to a thing (i.e. the name of a thing > defined elsewhere). For example, consider the production: > > NamedNumber ::= identifier "(" SignedNumber ")" > | identifier "(" DefinedValue ")" > I like solving this with either a (WriterT Parser) or using the Parsec state to lazily access the final mapping. Here is a working Toy example where 'finalMap' is used during the parsing. Parsec was a bit too strict with the return of 'parseVal' so I had to use a (data Box) to make it lazy: > import Text.ParserCombinators.Parsec > > import Data.Maybe > import qualified Data.Map as M > > data Box a = Box {unBox :: a} > > input = unlines $ > [ "name(ref)" > , "ref=7" > ] > > data Toy = Toy String Int deriving (Show) > > myParse s = toys where > result = runParser parser M.empty "Title" s > toys = either Left (Right . fst) result > > lookupRef r = Box (finalMap M.! r) > where finalMap = either undefined snd result > > parser = do > maybeToyList <- many parseLine > defMap <- getState > return (catMaybes maybeToyList,defMap) > > parseLine = try parseToy <|> parseDef <|> (char '\n' >> return Nothing) > > parseToy = do > name <- many1 letter > val <- between (char '(') (char ')') (try parseVal <|> parseRef) > return (Just (Toy name (unBox val))) > > parseVal = do > s <- many1 digit > return (Box (read s)) > > parseRef = do > s <- many1 letter > return (lookupRef s) > > parseDef = do > s <- many1 letter > char '=' > v <- parseVal > defMap <- getState > let defMap' = M.insert s (unBox v) defMap > setState $! defMap' > return Nothing When I run it in ghci I get: > *Main> myParse input > Right [Toy "name" 7] Cheers, Chris From jon.fairbairn at cl.cam.ac.uk Wed Aug 1 06:06:09 2007 From: jon.fairbairn at cl.cam.ac.uk (Jon Fairbairn) Date: Wed Aug 1 05:59:40 2007 Subject: [Haskell-cafe] Re: [Haskell] View patterns in GHC: Request?for?feedback References: <20070723090900.GA25820@cs.cmu.edu> <46A87C01.5020808@list.mightyreason.com> <200707270902.50113.jcast@ou.edu> <20070727175124.GB12477@darcs.net> <20070731223153.GD12386@darcs.net> Message-ID: David Roundy writes: > On Mon, Jul 30, 2007 at 11:47:46AM +0100, Jon Fairbairn wrote: > > [snippage] This is all very horrid, but as far as I can tell > > what I was proposing wouldn't lead to such a mess, except > > possibly via defaulting, which, as the least important > > aspect of the idea could easily be abandoned. > > What your suggestion would do would be to make the type inferred for every > pattern-matched function polymorphic, No it wouldn't. I reiterate: constructors would either belong to a class or to a datatype, so for constructors that belong to a datatype the situation would be exactly as before. It's unfortunate that when I wrote my example I assumed that everyone would understand that for some classes we would have defaults (because we already have this: the constructors for Integer effectively belong to a class and are defaulted to Integer). I'm now quite convinced that using defaults together with more general overloaded constructors would be a mistake, but that's all you've managed to convince me of! Yes, there is a problem that importing a class with a constructor into a scope that declares the same constructor as a data constructor would cause difficulties (namely the module would nolonger compile), but aren't they exactly the same difficulties as when the name in question is just a function name? -- J?n Fairbairn Jon.Fairbairn@cl.cam.ac.uk From wagner.andrew at gmail.com Wed Aug 1 08:43:28 2007 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Wed Aug 1 08:35:48 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> References: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> Message-ID: This seems wrong to me. A monad is, first and foremost, a type constructor class. I'm not sure how you can really compare that to a loop. But perhaps the easiest way to test your definition would be to ask this: How is, for example, the Maybe monad like a loop, in your definition? On 8/1/07, Kaveh Shahbazian wrote: > This is about to put a definition/description to test. So please cooperate! > ;) > Is this a useful ? sufficient, not complete ? definition/description for a > monad; for an imperative mind: (?) > > "A monad is like a loop that can run a new function against it's variable in > each iteration." > > (I insist on the simplicity! And I will resist any expansion of this > sentence (except for an exceptional note that I think of it hardly). > I think there is not any complete definitions in computer world. At least > there are many things to know when you want to use them in practice. So > please have this in mind and review me!) > > Cheers :) > > > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > > From ithika at gmail.com Wed Aug 1 08:54:24 2007 From: ithika at gmail.com (Dougal Stanton) Date: Wed Aug 1 08:46:45 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: References: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> Message-ID: <2d3641330708010554g303cc804v71a458605f1c240b@mail.gmail.com> On 01/08/07, Andrew Wagner wrote: > This seems wrong to me. A monad is, first and foremost, a type > constructor class. I'm not sure how you can really compare that to a > loop. But perhaps the easiest way to test your definition would be to > ask this: How is, for example, the Maybe monad like a loop, in your > definition? I am baffled by this discussion. I thought monads were something to do with boxes of toxic apples in space? Obviously we can relate monadic apples to arrows through the William Tell analogy. And erm... yeah. Still needs a little polishing. I just hope the whole metaphor isn't rotten to the core. I will be here all week. Please, try the spice cake. Cheers, D. From dav.vire+haskell at gmail.com Wed Aug 1 09:15:47 2007 From: dav.vire+haskell at gmail.com (david48) Date: Wed Aug 1 09:08:08 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: References: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> Message-ID: <4c88418c0708010615y2e688376x3842746028c67183@mail.gmail.com> On 8/1/07, Andrew Wagner wrote: > This seems wrong to me. A monad is, first and foremost, a type > constructor class. I'm not sure how you can really compare that to a > loop. But perhaps the easiest way to test your definition would be to > ask this: How is, for example, the Maybe monad like a loop, in your > definition? As a beginner haskeller coming from an imperative experience, I think I understood what he meant. say you have this code : putStrLn "1" >> putStrLn "2" >> putStrLn "3" you can imagine each of the calls to putStrLn gets implicitly passed a variable (here, the world ) and they happen in succession so it's "like a loop". Except that a loop... loops so the comparison is far fetched. From jim at sdf-eu.org Wed Aug 1 09:21:21 2007 From: jim at sdf-eu.org (Jim Burton) Date: Wed Aug 1 09:13:41 2007 Subject: [Haskell-cafe] Backpatching In-Reply-To: <1185950451.6796.1.camel@derek-laptop> References: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> <20070801060418.GB6033@localhost.localdomain> <1185950451.6796.1.camel@derek-laptop> Message-ID: <11945491.post@talk.nabble.com> Derek Elkins wrote: > > On Tue, 2007-07-31 at 23:04 -0700, Stefan O'Rear wrote: >> On Wed, Aug 01, 2007 at 03:44:32PM +1000, Thomas Conway wrote: >> > This sounds like a common problem type. Is there a well known solution >> > to this sort of problem? >> >> Mmm... logic programming? >> >> http://citeseer.ist.psu.edu/claessen00typed.html >> >> You'll only need the code for logic-variables, and even that can be >> simplified because your "terms" are non-recursive. (Even in the >> recursive case, a logic program like a HM typechecker usually only needs >> ~50 lines of prelude). > > If someone is interested, I did transcribe and mildly generalize the > code from that paper. > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > > Hi Derek, I'd be interested in looking at that -- have you put it online? -- View this message in context: http://www.nabble.com/Backpatching-tf4198168.html#a11945491 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. From cconway at cs.nyu.edu Wed Aug 1 09:27:26 2007 From: cconway at cs.nyu.edu (Christopher L Conway) Date: Wed Aug 1 09:19:48 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <4c88418c0708010615y2e688376x3842746028c67183@mail.gmail.com> References: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> <4c88418c0708010615y2e688376x3842746028c67183@mail.gmail.com> Message-ID: <4a051d930708010627t2d95ac9fg75537da8ac20f3ea@mail.gmail.com> On 8/1/07, david48 wrote: > As a beginner haskeller coming from an imperative experience, I think > I understood what he meant. > > say you have this code : > > putStrLn "1" >> putStrLn "2" >> putStrLn "3" > > you can imagine each of the calls to putStrLn gets implicitly passed a > variable (here, the world ) and they happen in succession so it's > "like a loop". Why isn't this "like a semicolon"? Chris From wagner.andrew at gmail.com Wed Aug 1 09:27:43 2007 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Wed Aug 1 09:20:04 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <4c88418c0708010615y2e688376x3842746028c67183@mail.gmail.com> References: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> <4c88418c0708010615y2e688376x3842746028c67183@mail.gmail.com> Message-ID: > say you have this code : > > putStrLn "1" >> putStrLn "2" >> putStrLn "3" > > you can imagine each of the calls to putStrLn gets implicitly passed a > variable (here, the world ) and they happen in succession so it's > "like a loop". It breaks down further as soon as you add any amount of complexity to the code as well. E.g.: putStrLn "1" >> getLine >>= \line -> putStrLn line >> putStrLn "end" This prints something, gets something from the user and prints it, and then prints something else. The equivalent imperative pseudo-code is something like: print "foo"; line = inputLine(); print line; print "end"; Not loop-ish at all! From dav.vire+haskell at gmail.com Wed Aug 1 09:59:35 2007 From: dav.vire+haskell at gmail.com (david48) Date: Wed Aug 1 09:51:55 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: References: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> <4c88418c0708010615y2e688376x3842746028c67183@mail.gmail.com> Message-ID: <4c88418c0708010659w4a4d15aekaefa34b6f2a9977b@mail.gmail.com> On 8/1/07, Andrew Wagner wrote: > > you can imagine each of the calls to putStrLn gets implicitly passed a > > variable (here, the world ) and they happen in succession so it's > > "like a loop". > It breaks down further as soon as you add any amount of complexity to > the code as well. E.g.: [....] > Not loop-ish at all! I totally agree I was just stating how I understood the original poster's statement :) Personally I showed haskell to a Friend last week end. To explain some monadic code I explained it somewhat this way ( please keep in mind that I'm a beginner so the explanation I gave him is probably not accurate ) I told him that in a lazy functional programming language you can't decide when a function gets evaluated or not. I then told him that it gets problematic if you want evaluate some functions in sequence. I also told him that haskell is a pure language, that is there is no side effects in the functions. I then told him that it's a problem if you want to interact with the outside world (IO) I explained that a monad is a way to get functions evaluated in a specific order, with a type such that you can't mix actions with pure functions. I told him that monads are just a special datatype and implementation of 2 functions : - a function that lets you evaluate a function before evaluating the next one, taking the output of the first function to feed the input of the second. - a function that takes a pure value and "promotes" to the monad's type. I told him that in the case of IO the datatype in question is IO and it contains data about the outside world, but there are many other monads, but I didn't go there too much because it's not totally clear for me. He seemed to be not too much confused by the concept, so I hope that I didn't told him too much inaccuracies... From dav.vire+haskell at gmail.com Wed Aug 1 10:05:43 2007 From: dav.vire+haskell at gmail.com (david48) Date: Wed Aug 1 09:58:03 2007 Subject: [Haskell-cafe] Indentation woes In-Reply-To: <7CEC32B7-F9B7-4312-9F63-A479DE0B2DBD@cs.otago.ac.nz> References: <20070726192337.GA4598@localhost.localdomain> <20070726220052.GA5028@localhost.localdomain> <7CEC32B7-F9B7-4312-9F63-A479DE0B2DBD@cs.otago.ac.nz> Message-ID: <4c88418c0708010705r67df16cawcc4db8caf25a2d24@mail.gmail.com> On the topic of indenting, it would be nice if there was a way to tell the compiler the size of the tab characters. The way it is now, I have to use space characters to indent. It's not really a problem though. From duncan.coutts at worc.ox.ac.uk Wed Aug 1 10:12:31 2007 From: duncan.coutts at worc.ox.ac.uk (Duncan Coutts) Date: Wed Aug 1 10:03:44 2007 Subject: [Haskell-cafe] Indentation woes In-Reply-To: <4c88418c0708010705r67df16cawcc4db8caf25a2d24@mail.gmail.com> References: <20070726192337.GA4598@localhost.localdomain> <20070726220052.GA5028@localhost.localdomain> <7CEC32B7-F9B7-4312-9F63-A479DE0B2DBD@cs.otago.ac.nz> <4c88418c0708010705r67df16cawcc4db8caf25a2d24@mail.gmail.com> Message-ID: <1185977551.5989.67.camel@localhost> On Wed, 2007-08-01 at 16:05 +0200, david48 wrote: > On the topic of indenting, it would be nice if there was a way to tell > the compiler the size of the tab characters. > > The way it is now, I have to use space characters to indent. Good! You're doing exactly the right thing according to the Haskell style guide: http://urchin.earth.li/~ian/style/haskell.html :-) Duncan From bf3 at telenet.be Wed Aug 1 10:26:47 2007 From: bf3 at telenet.be (peterv) Date: Wed Aug 1 10:19:21 2007 Subject: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer Message-ID: <00d401c7d447$fe1c1bd0$fa545370$@be> Kaveh> "A monad is like a loop that can run a new function against its variable in each iteration." I?m an imperative programmer learning Haskell, so I?m a newbie, but I?ll give it a try ? Making mistakes is the best way to learn it ;) There are lots of different kinds of monads, but let?s stick to the IO monad first, which you seem to refer to. No *an IO monad is not a loop at all*. Instead, from an imperative programmer?s point of view, the following might be better: ?an IO monad is a delayed action that will be executed as soon as that action is needed for further evaluation of the program.? The simple program main = getLine >>= putStrLn can be visually represented as (see attachment) The ?world? (=a representation of your computer?s hardware) is passed to the main function, which passes it to all actions that it encounters during its lazy evaluation, causing the executing of the actions as an effect. The red wire through which the ?world flows? is a ?single thread?, it cannot be split (because the physical world cannot be copied!!!), so no unwanted side effects can ever occur, making IO safe in Haskell. When you write your IO program, this world object is never available (the IO type is a special internal type), so the red wire is erased from the diagram, and the getLine and putStrLn boxes become ?delayed actions?. Imperative programmers like myself might initially be confused when they see Haskell?s do notation, because it looks like the actions are strict statements as in C/C++/Pascal/Java/C#/etc, but they are not. For example, try the following program: main = do last [ putStrLn "NOT executed although it is first in the list, as it is not used by the main function!", putStrLn "This action IS executed because it is evaluated by the main function." ] This is of course all due to Haskell?s laziness which only evaluates just those expressions that it needs to evaluate the main function. One thing to note in the diagram above is that the getLine box has TWO outputs, the String and the World. But functions can only have a single output, but this can be tuple. Hence the passing of the world from one box to the other is a bit more complicated. It is this pattern of extracting both values from the output and passing them to the next function and other related combinations that form the generic monad class, which can be used for many more things than IO. See http://haskell.org/haskellwiki/IO_inside for a much deeper and more correct explanation ? And for the pros here, did this newbie make any sense? Probably not ;-) Oh no, yet another monad explanation!!! Now the universe will most certainly collapse? No virus found in this outgoing message. Checked by AVG Free Edition. Version: 7.5.476 / Virus Database: 269.11.0/929 - Release Date: 31/07/2007 17:26 -------------- next part -------------- A non-text attachment was scrubbed... Name: IO monad.GIF Type: image/gif Size: 7808 bytes Desc: not available Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/32e3b083/IOmonad-0001.gif From A.M.Gimblett at swansea.ac.uk Wed Aug 1 10:28:01 2007 From: A.M.Gimblett at swansea.ac.uk (Andy Gimblett) Date: Wed Aug 1 10:20:27 2007 Subject: [Haskell-cafe] Cartesian product of a Set Message-ID: <20070801142801.GA7647@cspcag2.swan.ac.uk> Hi all, Is this a reasonable way to compute the cartesian product of a Set? > cartesian :: Ord a => S.Set a -> S.Set (a,a) > cartesian x = S.fromList [(i,j) | i <- xs, j <- xs] > where xs = S.toList x It's a fairly "obvious" way to do it, but I wondered if there were any hidden gotchas. I'm particularly concerned by toList (O(n)) fromList (O(n log n)) - but for other reasons I'd really like to be using Set rather than List for this (I think). Many thanks for any thoughts, -Andy -- Andy Gimblett Computer Science Department University of Wales Swansea http://www.cs.swan.ac.uk/~csandy/ From lgreg.meredith at biosimilarity.com Wed Aug 1 10:48:41 2007 From: lgreg.meredith at biosimilarity.com (Greg Meredith) Date: Wed Aug 1 10:41:02 2007 Subject: [Haskell-cafe] monads and groups -- instead of loops Message-ID: <5de3f5ca0708010748t2251bea9pa5a04ae227fb4ac0@mail.gmail.com> Haskellians, Though the actual metaphor in the monads-via-loops doesn't seem to fly with this audience, i like the spirit of the communication and the implicit challenge: find a pithy slogan that -- for a particular audience, like imperative programmers -- serves to uncover the essence of the notion. i can't really address that audience as my first real exposure to programming was scheme and i moved into concurrency and reflection after that and only ever used imperative languages as means to an end. That said, i think i found another metaphor that summarizes the notion for me. In the same way that the group axioms organize notions of symmetry, including addition, multiplication, reflections, translations, rotations, ... the monad(ic axioms) organize(s) notions of snapshot (return) and update (bind), including state, i/o, control, .... In short group : symmetry :: monad : update Best wishes, --greg -- L.G. Meredith Managing Partner Biosimilarity LLC 505 N 72nd St Seattle, WA 98103 +1 206.650.3740 http://biosimilarity.blogspot.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/2c03d3f5/attachment.htm From allbery at ece.cmu.edu Wed Aug 1 10:58:19 2007 From: allbery at ece.cmu.edu (Brandon S. Allbery KF8NH) Date: Wed Aug 1 10:50:42 2007 Subject: [Haskell-cafe] Indentation woes In-Reply-To: <4c88418c0708010705r67df16cawcc4db8caf25a2d24@mail.gmail.com> References: <20070726192337.GA4598@localhost.localdomain> <20070726220052.GA5028@localhost.localdomain> <7CEC32B7-F9B7-4312-9F63-A479DE0B2DBD@cs.otago.ac.nz> <4c88418c0708010705r67df16cawcc4db8caf25a2d24@mail.gmail.com> Message-ID: <61D2DF2B-56E8-4291-B350-5383FE9E1FCA@ece.cmu.edu> On Aug 1, 2007, at 10:05 , david48 wrote: > On the topic of indenting, it would be nice if there was a way to tell > the compiler the size of the tab characters. > > The way it is now, I have to use space characters to indent. The problem with that is, while there's a standard for the width of a tab on Unix, there isn't on Windows. It's really only safe to use spaces for indentation. Thus, it's better to use an editor which converts tabs to spaces in a specified manner, so you can use whatever tabs you're comfortable with (or none; Emacs generally uses tab to mean "indent appropriately") but the resulting file uses spaces and will behave reliably anywhere. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH From dav.vire+haskell at gmail.com Wed Aug 1 11:04:02 2007 From: dav.vire+haskell at gmail.com (david48) Date: Wed Aug 1 10:56:23 2007 Subject: [Haskell-cafe] Indentation woes In-Reply-To: <61D2DF2B-56E8-4291-B350-5383FE9E1FCA@ece.cmu.edu> References: <20070726192337.GA4598@localhost.localdomain> <20070726220052.GA5028@localhost.localdomain> <7CEC32B7-F9B7-4312-9F63-A479DE0B2DBD@cs.otago.ac.nz> <4c88418c0708010705r67df16cawcc4db8caf25a2d24@mail.gmail.com> <61D2DF2B-56E8-4291-B350-5383FE9E1FCA@ece.cmu.edu> Message-ID: <4c88418c0708010804y4b663ce0u1f082ab9098ae526@mail.gmail.com> On 8/1/07, Brandon S. Allbery KF8NH wrote: > > On Aug 1, 2007, at 10:05 , david48 wrote: > > > On the topic of indenting, it would be nice if there was a way to tell > > the compiler the size of the tab characters. > > > > The way it is now, I have to use space characters to indent. > > The problem with that is, while there's a standard for the width of a > tab on Unix, there isn't on Windows. It's really only safe to use > spaces for indentation. On second thought, I don't even know why I posted this. There's so many things far more important that tabs, and using spaces is truly the only safe way. Sorry for the noise. From wagner.andrew at gmail.com Wed Aug 1 11:14:36 2007 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Wed Aug 1 11:06:57 2007 Subject: [Haskell-cafe] monads and groups -- instead of loops In-Reply-To: <5de3f5ca0708010748t2251bea9pa5a04ae227fb4ac0@mail.gmail.com> References: <5de3f5ca0708010748t2251bea9pa5a04ae227fb4ac0@mail.gmail.com> Message-ID: That's great, unless the imperative programmer happens to be one of the 90% of programmers that isn't particularly familiar with group theory... On 8/1/07, Greg Meredith wrote: > Haskellians, > > Though the actual metaphor in the monads-via-loops doesn't seem to fly with > this audience, i like the spirit of the communication and the implicit > challenge: find a pithy slogan that -- for a particular audience, like > imperative programmers -- serves to uncover the essence of the notion. i > can't really address that audience as my first real exposure to programming > was scheme and i moved into concurrency and reflection after that and only > ever used imperative languages as means to an end. That said, i think i > found another metaphor that summarizes the notion for me. In the same way > that the group axioms organize notions of symmetry, including addition, > multiplication, reflections, translations, rotations, ... the monad(ic > axioms) organize(s) notions of snapshot (return) and update (bind), > including state, i/o, control, .... In short > > group : symmetry :: monad : update > > Best wishes, > > --greg > > -- > L.G. Meredith > Managing Partner > Biosimilarity LLC > 505 N 72nd St > Seattle, WA 98103 > > +1 206.650.3740 > > http://biosimilarity.blogspot.com > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > > From wagner.andrew at gmail.com Wed Aug 1 11:31:45 2007 From: wagner.andrew at gmail.com (Andrew Wagner) Date: Wed Aug 1 11:24:04 2007 Subject: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <00d401c7d447$fe1c1bd0$fa545370$@be> References: <00d401c7d447$fe1c1bd0$fa545370$@be> Message-ID: > > "an IO monad is a delayed action that will be executed as soon as that action is needed for further evaluation of the program." > I'm not sure I like this, as it seems to confuse the issue. An expert should correct me if I'm wrong, but monads in and of themselves don't depend on laziness. Rather, *everything* in haskell is lazy, unless explicitly strict-ified. As for the rest of your email, I don't necessarily disagree, but don't find it particularly helpful either. Which may, of course, be a personal thing. For me, I think the key to monads is to really understand 2 things about them: 1.) They are simply type constructor classes 2.) Monads are about sequencing For point 2, think about the two main things you have to define to create an instance of a monad: (>>=) :: m a -> (a -> m b) -> m b That is, you have two monadic actions, m a and m b, and bind says how to take the result of the first and fit it into the second -- in sequence! (>>) :: m a -> m b -> m b Again, we have 2 monadic actions that we're composing, in sequence. This time, we're just discarding the result of the first. From jgbailey at gmail.com Wed Aug 1 11:36:00 2007 From: jgbailey at gmail.com (Justin Bailey) Date: Wed Aug 1 11:28:20 2007 Subject: [Haskell-cafe] Knuth Morris Pratt for Lazy Bytestrings implementation In-Reply-To: <20070801020709.GF21697@cse.unsw.EDU.AU> References: <20070801020709.GF21697@cse.unsw.EDU.AU> Message-ID: On 7/31/07, Donald Bruce Stewart wrote: > jgbailey: > Also, be sure to compare against a naive search, optimised for > strict and lazy bytestrings, > > http://hpaste.org/1803 > > If its not faster than those 2, then you're doing something wrong :) > > -- Don Yes, I was really hoping someone (dons :)) would look at my code and give any suggestions. Did the attachment come through? Justin From jgbailey at gmail.com Wed Aug 1 11:39:29 2007 From: jgbailey at gmail.com (Justin Bailey) Date: Wed Aug 1 11:31:50 2007 Subject: [Haskell-cafe] Knuth Morris Pratt for Lazy Bytestrings implementation In-Reply-To: <59534.203.185.215.144.1185929486.squirrel@dockerz.net> References: <59534.203.185.215.144.1185929486.squirrel@dockerz.net> Message-ID: On 7/31/07, Tim Docker wrote: > Now I wonder what that 7MB file might be? :-) > > We (team TNT) implemented KMP over lazy bytestrings as part of our icfp > 2007 contest entry. As I remember, for the DNA evaluator it gave modest > speed improvements over more na?ve searching. Our implementation was based > upon this blog post: > > http://twan.home.fmf.nl/blog/ > > Tim What prompted this was we adapted Oleg's KMP module for PackedStrings to lazy bytestrings, and it was too slow. I am actually interested in implementing KMP for Data.Sequence, but wanted to get bytestrings out of the way first. Justin From mail at joachim-breitner.de Wed Aug 1 11:52:10 2007 From: mail at joachim-breitner.de (Joachim Breitner) Date: Wed Aug 1 11:44:32 2007 Subject: [Haskell-cafe] Cartesian product of a Set In-Reply-To: <20070801142801.GA7647@cspcag2.swan.ac.uk> References: <20070801142801.GA7647@cspcag2.swan.ac.uk> Message-ID: <1185983530.4312.36.camel@otto.ehbuehl.net> Hi, Am Mittwoch, den 01.08.2007, 15:28 +0100 schrieb Andy Gimblett: > Hi all, > > Is this a reasonable way to compute the cartesian product of a Set? > > > cartesian :: Ord a => S.Set a -> S.Set (a,a) > > cartesian x = S.fromList [(i,j) | i <- xs, j <- xs] > > where xs = S.toList x > > It's a fairly "obvious" way to do it, but I wondered if there were any > hidden gotchas. I'm particularly concerned by toList (O(n)) fromList > (O(n log n)) - but for other reasons I'd really like to be using Set > rather than List for this (I think). Using only functions from the Set module, you could write: > catesian s = fold (\v prod -> prod `union` map ((,)v) s ) empty s But this won?t be faster, I guess, as map is O(n?log n) and fold is O(n) OTOH, ((,)v) should be monotonic, so it might be faster (and hopefully still correct) to write: > catesian s = fold (\v prod -> prod `union` mapMonotonic ((,)v) s ) empty s Greetings, Joachim -- Joachim Breitner e-Mail: mail@joachim-breitner.de Homepage: http://www.joachim-breitner.de ICQ#: 74513189 From dpiponi at gmail.com Wed Aug 1 12:01:58 2007 From: dpiponi at gmail.com (Dan Piponi) Date: Wed Aug 1 11:54:18 2007 Subject: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: References: <00d401c7d447$fe1c1bd0$fa545370$@be> Message-ID: <625b74080708010901m65a14b98j1d17188bcc606c6@mail.gmail.com> On 8/1/07, Andrew Wagner wrote: > For me, I think the key to monads is to really > understand 2 things about them: > ... > 2.) Monads are about sequencing Now I disagree on 2. Monads are no more about sequencing than binary operators are about sequencing. Sure, if you want to, you can define an operator like (*) to be non-commutative, so that a*b is different to b*a, but that doesn't really get to the essence of what a binary operator is. And in everyday usage we use (*) to mean ordinary commutative multiplication where there is no sense of sequencing. The same holds for monads. If you want to use them for sequencing the option is there, but there are plenty of commutative monads out there, for which the order of operations doesn't matter, and the fact that they are commutative doesn't make them any less monads. So while you can use monads to sequence, I don't think sequencing gets to the essence of what monads are. I suspect I hold a minority view here... :-) -- Dan From dukedave at gmail.com Wed Aug 1 12:08:22 2007 From: dukedave at gmail.com (Dave Tapley) Date: Wed Aug 1 12:00:42 2007 Subject: [Haskell-cafe] Exiting GLUT application In-Reply-To: References: <200707312316.09949.coeus@gmx.de> Message-ID: Unfortunately whilst the new code is returning me to a 'Main >' prompt as required another problem has come up. The issue here is found when the code is executed in both GHCi (6.6) and hugs (20050308). Once the code below is loaded evaluating main opens an unfilled window as required. However if this window is closed and main is evaluated again both GHCi and hugs die thus: GHCi: Illegal instruction (core dumped) hugs: Unexpected signal Any thoughts? On 31/07/07, Dave Tapley wrote: > Excellent, thank you Marc your advice worked perfectly. > > For reference the corrected code reads: > > > import Graphics.UI.GLUT > > main = do > > getArgsAndInitialize > > createWindow "" > > actionOnWindowClose $= ContinueExectuion > > mainLoop > > Dave, > > > On 31/07/07, Marc A. Ziegert wrote: > > in old glut, the main loop was the core of the single threaded program. exiting it did mean to exit the program completely. > > in freeglut, you have alternatives. but for compatibility, it defaults to the old behaviour. > > > > > > > > - marc > > > > > > Am Dienstag, 31. Juli 2007 19:16 schrieb Dave Tapley: > > > Hi everyone, I have the following skeleton GLUT code: > > > > > > > import Graphics.UI.GLUT > > > > main = do > > > > getArgsAndInitialize > > > > createWindow "" > > > > mainLoop > > > > > > It loads into both hugs and ghci fine and when 'main' is evaluated an > > > empty window opens as expected. > > > However when closing the window (clicking the window manager's x > > > button) both hugs and ghci exit with the window, as opposed to > > > returning to the the 'Main>' prompt. > > > > > > I suspect I need some callback to exit the GUI cleanly? > > > > > > Cheers, > > > Dave > > > _______________________________________________ > > > Haskell-Cafe mailing list > > > Haskell-Cafe@haskell.org > > > http://www.haskell.org/mailman/listinfo/haskell-cafe > > > > > > > > From jeff.polakow at db.com Wed Aug 1 12:11:51 2007 From: jeff.polakow at db.com (Jeff Polakow) Date: Wed Aug 1 12:04:15 2007 Subject: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <625b74080708010901m65a14b98j1d17188bcc606c6@mail.gmail.com> Message-ID: Hello, > On 8/1/07, Andrew Wagner wrote: > > For me, I think the key to monads is to really > > understand 2 things about them: > > ... > > 2.) Monads are about sequencing > > Now I disagree on 2. > > Monads are no more about sequencing than binary operators are about > sequencing. Sure, if you want to, you can define an operator like (*) > to be non-commutative, so that a*b is different to b*a, but that > doesn't really get to the essence of what a binary operator is. And in > everyday usage we use (*) to mean ordinary commutative multiplication > where there is no sense of sequencing. > > The same holds for monads. If you want to use them for sequencing the > option is there, but there are plenty of commutative monads out there, > for which the order of operations doesn't matter, and the fact that > they are commutative doesn't make them any less monads. So while you > can use monads to sequence, I don't think sequencing gets to the > essence of what monads are. > > I suspect I hold a minority view here... :-) > You are entirely correct. Data dependencies enforce/specify sequencing. -Jeff --- This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/33b88c2c/attachment.htm From dukedave at gmail.com Wed Aug 1 12:30:53 2007 From: dukedave at gmail.com (Dave Tapley) Date: Wed Aug 1 12:23:12 2007 Subject: [Haskell-cafe] renderString problems Message-ID: Hi all, I'm having a lot of trouble using renderString from Graphics.UI.GLUT.Fonts. All my attempts to render a StrokeFont have so far failed. Using a BitmapFont I can get strings to appear but they demonstrate the odd behaviour of translating themselves a distance equal to their length every time my displayCallback function is evaluated. My requests are: * Does anyone know how to keep the position fixed? * Are there any good examples of (working) GLUT code available on the web, I'm finding it very hard to make any progress at the moment. Certainly not at Haskell speed :( I am using the following code: > import Graphics.UI.GLUT > main = do > getArgsAndInitialize > createWindow "" > displayCallback $= update > actionOnWindowClose $= ContinueExectuion > mainLoop > > update = do > clear [ColorBuffer] > renderString Fixed8By13 $ "Test string" > flush Cheers, Dave From sethg at ropine.com Wed Aug 1 12:39:14 2007 From: sethg at ropine.com (Seth Gordon) Date: Wed Aug 1 12:31:37 2007 Subject: [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> References: <8aa524530708010002n3a91f9dds6582d45cb5924556@mail.gmail.com> Message-ID: <46B0B732.1010905@ropine.com> My own perspective on monads is this: In procedural and OO languages, when dealing with compound data structures, we think in terms of getters (*taking data out* of the structure) and setters (*putting data in* to the structure). Languages with some impure functional features (Lisp, Scheme, Perl, Python) let you operate on lists with a "map" function ("mapcar" in Common Lisp), where instead of *taking data out* of a list, you *put a function in*, and the function manipulates each element without being aware of the context. You *turn the data structure inside-out*, as it were, so you don't have to think about how the elements are accessed. Functors are a generalization from lists to "things that can be mapped over" in general, and then monads are a generalization of functors. Haskell solves the "how can I do I/O in a pure functional language" problem by *turning the world inside-out*. Instead of taking data from the mutable outside world, using functions to manipulate it, and depositing results back into that world, you put your functions into the IO monad. It's like the joke about how a theoretical mathematician catches an elephant: build a cage, go inside, close the door, and redefine outside as inside. From misc at alpheccar.org Wed Aug 1 13:13:15 2007 From: misc at alpheccar.org (alpheccar) Date: Wed Aug 1 13:03:46 2007 Subject: RE [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <00d401c7d447$fe1c1bd0$fa545370$@be> References: <00d401c7d447$fe1c1bd0$fa545370$@be> Message-ID: > Kaveh> "A monad is like a loop that can run a new function against > its variable in each iteration." > > I?m an imperative programmer learning Haskell, so I?m a newbie, > but I?ll give it a try ? Making mistakes is the best way to > learn it ;) > I was a newbie not so long ago so I can understand the trouble of imperative programmers when they meet monads for the first time. I think the problem is due to a few bad tutorial still available on the web and which are making two mistakes: 1 - Focusing on the IO monad which is very special ; 2 - Detailing the implementation. As a newie we don't care and we would prefer to see how to use monads rather than how to develop monads. When you look at monads you see they can be used for controlling the evaluation order (list monad, error monad, IO monad). They can be used for side effects (IO, state monad). They can be seen as containers (list, Maybe). They can be used to provide a protected environment (tainting). So, it is difficult to see what they have in common. Of course, what they have in common is a set of algebraic laws : the monadic laws but it does not help to know it. I think that a way to see monads (and a consequence of the monadic laws) is that monads are interpreters for domain specific languages. Each monad will generally come with a runMonad function (runReader, runWriter etc...) to execute the monadic program. IO is different because runIO is controlled by the runtime and cannot be manipulated by the user. The monadic combinators >>= are used to build programs. It is a way to concatenate two small programs to create a bigger one. In fact a combinator like >>= is doing two things : building new sentences of your domain specific language and evaluating them. if you take the list monad as example : [1,2,3] >>= \x -> [x*2,x*3]. First a new sentence will be created : [[2,3],[4,6],[6,9]]. Then, it is evaluated to give [2,3,4,6,6,9]. Here the interesting part is the sentence construction one. In other monads it may be the evaluation one. So, instead of building a big sentence and then evaluating it, a monad is a dynamical interpreter. The sentences are built and evaluated progressively. But of course, as I said, I was a newbie not long ago so the experts will correct me if needed. Now, a bit of self promotion but just because it may help. I have summarized the problems I faced when I was a newbie learning Haskell : http://www.alpheccar.org/en/posts/show/67 Some people told me it was useful. It is a summary of how imperative programmers should change their state of mind to understand the Haskell way. alpheccar. > There are lots of different kinds of monads, but let?s stick to > the IO monad first, which you seem to refer to. > > No *an IO monad is not a loop at all*. Instead, from an imperative > programmer?s point of view, the following might be better: > > ?an IO monad is a delayed action that will be executed as soon as > that action is needed for further evaluation of the program.? > > The simple program > > main = getLine >>= putStrLn > > can be visually represented as (see attachment) > > The ?world? (=a representation of your computer?s hardware) is > passed to the main function, which passes it to all actions that it > encounters during its lazy evaluation, causing the executing of the > actions as an effect. > > The red wire through which the ?world flows? is a ?single > thread?, it cannot be split (because the physical world cannot be > copied!!!), so no unwanted side effects can ever occur, making IO > safe in Haskell. > > When you write your IO program, this world object is never > available (the IO type is a special internal type), so the red wire > is erased from the diagram, and the getLine and putStrLn boxes > become ?delayed actions?. > > Imperative programmers like myself might initially be confused when > they see Haskell?s do notation, because it looks like the actions > are strict statements as in C/C++/Pascal/Java/C#/etc, but they are > not. > > For example, try the following program: > > main = do last [ > putStrLn "NOT executed although it is first in the list, > as it is not used by the main function!", > putStrLn "This action IS executed because it is > evaluated by the main function." ] > > This is of course all due to Haskell?s laziness which only > evaluates just those expressions that it needs to evaluate the main > function. > > One thing to note in the diagram above is that the getLine box has > TWO outputs, the String and the World. But functions can only have > a single output, but this can be tuple. Hence the passing of the > world from one box to the other is a bit more complicated. It is > this pattern of extracting both values from the output and passing > them to the next function and other related combinations that form > the generic monad class, which can be used for many more things > than IO. > > See http://haskell.org/haskellwiki/IO_inside for a much deeper and > more correct explanation ? > > And for the pros here, did this newbie make any sense? Probably > not ;-) > > Oh no, yet another monad explanation!!! Now the universe will most > certainly collapse? > > > No virus found in this outgoing message. > Checked by AVG Free Edition. > Version: 7.5.476 / Virus Database: 269.11.0/929 - Release Date: > 31/07/2007 17:26 > > > > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe From lgreg.meredith at biosimilarity.com Wed Aug 1 13:12:32 2007 From: lgreg.meredith at biosimilarity.com (Greg Meredith) Date: Wed Aug 1 13:04:56 2007 Subject: [Haskell-cafe] monads and groups -- instead of loops In-Reply-To: References: <5de3f5ca0708010748t2251bea9pa5a04ae227fb4ac0@mail.gmail.com> Message-ID: <5de3f5ca0708011012v805034egaef852ece0b13bd3@mail.gmail.com> Andrew, ;-) Agreed! As i said in my previous post, i can't address the imperative programmer. i really don't think that way and have a hard time understanding people who do! (-; Best wishes, --greg On 8/1/07, Andrew Wagner wrote: > > That's great, unless the imperative programmer happens to be one of > the 90% of programmers that isn't particularly familiar with group > theory... > > On 8/1/07, Greg Meredith wrote: > > Haskellians, > > > > Though the actual metaphor in the monads-via-loops doesn't seem to fly > with > > this audience, i like the spirit of the communication and the implicit > > challenge: find a pithy slogan that -- for a particular audience, like > > imperative programmers -- serves to uncover the essence of the notion. i > > can't really address that audience as my first real exposure to > programming > > was scheme and i moved into concurrency and reflection after that and > only > > ever used imperative languages as means to an end. That said, i think i > > found another metaphor that summarizes the notion for me. In the same > way > > that the group axioms organize notions of symmetry, including addition, > > multiplication, reflections, translations, rotations, ... the monad(ic > > axioms) organize(s) notions of snapshot (return) and update (bind), > > including state, i/o, control, .... In short > > > > group : symmetry :: monad : update > > > > Best wishes, > > > > --greg > > > > -- > > L.G. Meredith > > Managing Partner > > Biosimilarity LLC > > 505 N 72nd St > > Seattle, WA 98103 > > > > +1 206.650.3740 > > > > http://biosimilarity.blogspot.com > > _______________________________________________ > > Haskell-Cafe mailing list > > Haskell-Cafe@haskell.org > > http://www.haskell.org/mailman/listinfo/haskell-cafe > > > > > -- L.G. Meredith Managing Partner Biosimilarity LLC 505 N 72nd St Seattle, WA 98103 +1 206.650.3740 http://biosimilarity.blogspot.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/0c4f17e5/attachment-0001.htm From haskell at list.mightyreason.com Wed Aug 1 14:04:25 2007 From: haskell at list.mightyreason.com (ChrisK) Date: Wed Aug 1 13:56:54 2007 Subject: [Haskell-cafe] Re: Knuth Morris Pratt for Lazy Bytestrings implementation In-Reply-To: References: <20070801020709.GF21697@cse.unsw.EDU.AU> Message-ID: <46B0CB29.5080101@list.mightyreason.com> Justin Bailey wrote: > On 7/31/07, Donald Bruce Stewart wrote: >> jgbailey: >> Also, be sure to compare against a naive search, optimised for >> strict and lazy bytestrings, >> >> http://hpaste.org/1803 >> >> If its not faster than those 2, then you're doing something wrong :) >> >> -- Don > > Yes, I was really hoping someone (dons :)) would look at my code and > give any suggestions. Did the attachment come through? > > Justin I will make measurements. I already see that > {-# OPTIONS_GHC -fbang-patterns #-} > module KMPSeq (kmpMatch) > kmpMatch' :: B.ByteString -> Int64 -> Int -> Int64 > kmpMatch' !str !currIdx !patShift > let matchLength' !pat !str !cnt | B.null pat = {-# SCC "kmpMatch_nullPatStr" #-} cnt > matchLength' !pat !str !cnt | B.null str = {-# SCC "kmpMatch_nullStr" #-} 0 > matchLength' !pat !str !cnt | (B.head pat == B.head str) = {-# SCC "kmpMatch_eqHead" #-} Is a huge win. It now uses 3 MB instead of 243 MB and runs faster. -- Chris From iahogsp at gmail.com Wed Aug 1 14:06:55 2007 From: iahogsp at gmail.com (Isto Aho) Date: Wed Aug 1 13:59:14 2007 Subject: [Haskell-cafe] Re: HDBC or HSQL In-Reply-To: <46B00D4F.6090206@alexjacobson.com> References: <470880360707300831s44170261lb5d2002d1f56e70b@mail.gmail.com> <46B00D4F.6090206@alexjacobson.com> Message-ID: <470880360708011106h30e646dai3b79ce8f673f5ac1@mail.gmail.com> Hi, I'd like to store small matrices into a db. Number of rows and columns may vary in a way not known in advance. One might use a relation (matrixId, col, row, value) or something like that but if it is possible to put a matrix in one command into db, some queries will be easier. E.g., one relation can store several matrices and it would be easy to query, how many matrices are stored currently. With that above four tuple you can find out the number of unique matrixId's, too, but it is not as easy as with matrices. Anyhow, now I'm not sure if I should stick with HSQL any more... Earlier comments on this thread made me think that maybe it would be a better idea to try to learn enough HDBC. This would be used in a server application. Is HAppS applicable here? e.g. after some tweaking the following works with HSQL: addRows = do dbh <- connect server database user_id passwd intoDB dbh ([555,111, 50, 1000]::[Int]) ([21.0,22.0,23.0,24.0 ]::[Double]) intoDB dbh ([556,111, 50, 1000]::[Int]) ([21.0,22.0,23.0,24.0 ]::[Double]) intoDB dbh ([]::[Int]) ([]::[Double]) where intoDB dbh i_lst d_lst = catchSql (do let cmd = "INSERT INTO trial (intList, dList) VALUES (" ++ toSqlValue i_lst ++ "," ++ toSqlValue d_lst ++ ")" execute dbh cmd ) (\e -> putStrLn $ "Problem: " ++ show e) Similarly, queries can handle matrices and I like that it is now possible to select those columns or rows from the stored matrix that are needed. E.g. retrieveRecords2 :: Connection -> IO [[Double]] retrieveRecords2 c = do -- query c "select dList[1:2] from trial" >>= collectRows getRow query c "select dList from trial" >>= collectRows getRow where getRow :: Statement -> IO [Double] getRow stmt = do lst <- getFieldValue stmt "dList" return lst readTable2 = do dbh <- connect server database user_id passwd values <- retrieveRecords2 dbh putStrLn $ "dLists are : " ++ (show values) br, Isto 2007/8/1, Alex Jacobson : > > Out of curiosity, can I ask what you are actually trying to do? > > I am asking because I am trying to make HAppS a reasonable replacement > for all contexts in which you would otherwise use an external relational > database except those in which an external SQL database is a specific > requirement. > > -Alex- > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/2e41235c/attachment.htm From bos at serpentine.com Wed Aug 1 14:31:52 2007 From: bos at serpentine.com (Bryan O'Sullivan) Date: Wed Aug 1 14:24:57 2007 Subject: [Haskell-cafe] OS swapping and haskell data structures In-Reply-To: <46B01E14.2020109@alexjacobson.com> References: <46B01E14.2020109@alexjacobson.com> Message-ID: <46B0D198.2040506@serpentine.com> Alex Jacobson wrote: > If you create a Data.Map or Data.Set larger than fits in physical > memory, will OS level swapping enable your app to behave reasonably or > will things just die catastrophically as you hit a memory limit? Relying on the OS to page portions of your app in and out should always be the fallback of last resort. You are fairly guaranteed to get terrible performance because the VM subsystem can't anticipate your app's memory access patterns, and catastrophic death of either your app or other system processes is a strong possibility (Google for "OOM killer" if you want some horror stories). In many cases, you can't even rely on paging being possible. References: <46B01E14.2020109@alexjacobson.com> <46B0D198.2040506@serpentine.com> Message-ID: <1185993632.5989.79.camel@localhost> On Wed, 2007-08-01 at 11:31 -0700, Bryan O'Sullivan wrote: > Alex Jacobson wrote: > > If you create a Data.Map or Data.Set larger than fits in physical > > memory, will OS level swapping enable your app to behave reasonably or > > will things just die catastrophically as you hit a memory limit? > > Relying on the OS to page portions of your app in and out should always > be the fallback of last resort. You are fairly guaranteed to get > terrible performance because the VM subsystem can't anticipate your > app's memory access patterns, and catastrophic death of either your app > or other system processes is a strong possibility (Google for "OOM > killer" if you want some horror stories). In many cases, you can't even > rely on paging being possible. Furthermore, as I understand it, GC does not interact well with paging since the GC has to traverse the data structures on major GCs it'll force it all to be kept in memory. Duncan From apfelmus at quantentunnel.de Wed Aug 1 14:42:22 2007 From: apfelmus at quantentunnel.de (apfelmus) Date: Wed Aug 1 14:34:42 2007 Subject: [Haskell-cafe] Re: Zippers, Random Numbers & Terrain In-Reply-To: <784a62100707292326u2b8fb37bl5fccb9b0c86ecf4c@mail.gmail.com> References: <784a62100707292326u2b8fb37bl5fccb9b0c86ecf4c@mail.gmail.com> Message-ID: Thomas Conway wrote: > This got me thinking that it would be cool to make an infinite terrain > generator using a zipper, so you can zoom in/out infinitely, and by > implication, infinitely in any direction. After some pondering, I think it's indeed possible and the zipper is the right tool for the job. I'll present the idea for constructing a one-dimensional "fractal terrain" but it generalizes to higher dimensions. First, consider the task to construct a 1D fractal height function defined on a bounded interval like [0,1]. type Pos = Double type Height = Double terrain :: Interval -> Pos -> Height We construct the terrain by dividing the interval in half and adjust the height of the midpoint randomly relative to the mean of the other heights. data Interval = I (Pos,Pos) (Height,Height) StdGen terrain :: Interval -> Pos -> Height terrain i x | x `in` left = terrain left x | x `in` right = terrain right x where (left, right) = bisect i in :: Pos -> Interval -> Bool in x (I (a,b) _ _) = a <= x && x <= b bisect :: Interval -> (Interval, Interval) bisect (I (a,b) (ha,hb) g) = (I (a,m) (ha,h) ga, I (m,b) (h,hb) gb) where m = (a+b)/2 h = (ha+hb)/2 + d * (a-b) * scale (d,g') = randomR (0,1) g (ga,gb) = split g' The factor scale controls the roughness of the terrain. True enough, the function terrain never returns but that shouldn't be an issue to the mathematician ;) Of course, we have to stop as soon as the interval length is smaller than some given resolution epsilon (i.e. the width of a pixel). Splitting the random number generator is not necessarily a good idea, but I don't care right now. For zoom-in, we want to specify different epsilons and get the same random values each time. So, we memoize the steps to produce the height function in an infinite tree data Terrain = Branch Terrain (Height,Height) Terrain terrain :: Interval -> Terrain terrain i = Branch (terrain left) h (terrain right) where (left, right) = bisect i I _ h _ = i The actual rendering can be obtained from the infinite Terrain, I'll omit it for simplicity. For finite zoom-out, we use a zipper type Zipper = (Context, Terrain) type Context = [Either Terrain Terrain] zoomInLeft, zoomInRight :: Zipper -> Zipper zoomInLeft (xs, Branch l h r) = (Left r:xs, l) zoomInRight (xs, Branch l h r) = (Right l:xs, r) zoomOut :: Zipper -> Zipper zoomOut (x:xs, t) = case x of Left r -> (xs, Branch t (t `joinHeights` r) r) Right l -> (xs, Branch l (l `joinHeights` t) t) where joinHeights (Branch _ (ha,_) _) (Branch _ (_,hb) _) = (ha,hb) zoomOut ([], _) = error "You fell out of the picture!" Mnemonics: Left means that we descended into the left half, Right that we descended into the right half of the interval. The final step is to allow infinite zoom-out. How to do that? Well, assume that we generate the landscape on the interval [0,1] and zoom out. The reverse of this would be to create the landscape on the interval [-1,1] and then zoom into the right half [0,1]. In other words, we view [0,1] as the right half of the bigger interval [-1,1]. This in turn can be viewed as the left half of the even bigger interval [-1,3]. In order to grow both interval bounds to infinity, we alternate between viewing it as left half and as right half. In other words, the insight is that *we're inside an infinite context*! Thus, generating an infinite terrain is like generating a finite one except that we need to generate the infinite context as well: terrainInfinite :: Interval -> Zipper terrainInfinite i = (right i, terrain i) where right (I (m,b) (h,hb) g) = Right (terrain l) : left i where l = fst $ bisect i i = I (a,b) (ha,hb) g' a = m - (b -m) ha = hb - (hb-h) + d * (a-b) * scale (d,g') = randomR (0,1) g left (I (a,m) (ha,h) g) = Left (terrain r) : right i where r = snd $ bisect i i = I (a,b) (ha,hb) g' b = m + (m-a ) hb = h + (h-ha) + d * (a-b) * scale (d,g') = randomR (0,1) g Here, left starts by extending a given interval to the right and right starts by extending it to the left. It would be nice to run the random generator backwards, the generator transitions in terrainInfinite are surely wrong, i.e. too deterministic. Also, the scale of the random height adjustment d is probably wrong. But those things are exercises for the attentive reader ;) That concludes the infinite terrain generation for one dimension. For higher dimension, one just needs to use 2D objects instead of intervals to split into two or more pieces. For instance, one can divide equilateral triangles into 4 smaller ones. In fact, it doesn't matter whether the starting triangle is equilateral or not when using the midpoints of the three sides to split it into four smaller triangles. Regards, apfelmus From lgreg.meredith at biosimilarity.com Wed Aug 1 15:23:26 2007 From: lgreg.meredith at biosimilarity.com (Greg Meredith) Date: Wed Aug 1 15:15:48 2007 Subject: [Haskell-cafe] Re: monads and groups -- instead of loops In-Reply-To: <5de3f5ca0708010748t2251bea9pa5a04ae227fb4ac0@mail.gmail.com> References: <5de3f5ca0708010748t2251bea9pa5a04ae227fb4ac0@mail.gmail.com> Message-ID: <5de3f5ca0708011223y322ec175p8b30422d5de76b3d@mail.gmail.com> Haskellians, But, along these lines i have been wondering for a while... the monad laws present an alternative categorification of monoid. At least it's alternative to monoidoid. In the spirit of this thought, does anyone know of an expansion of the monad axioms to include an inverse action? Here, i am following an analogy monoidoid : monad :: groupoid : ??? i did a search of the literature, but was probably using the wrong terminology to try to find references. i would be very grateful for anyone who might point me in the right direction. My intuition tells me this could be quite generally useful to computing in situation where boxing and updating have natural (or yet to be discovered) candidates for undo operations. i'm given to understand reversible computing might be a good thing to be thinking about if QC ever gets real... ;-) Best wishes, --greg On 8/1/07, Greg Meredith wrote: > > Haskellians, > > Though the actual metaphor in the monads-via-loops doesn't seem to fly > with this audience, i like the spirit of the communication and the implicit > challenge: find a pithy slogan that -- for a particular audience, like > imperative programmers -- serves to uncover the essence of the notion. i > can't really address that audience as my first real exposure to programming > was scheme and i moved into concurrency and reflection after that and only > ever used imperative languages as means to an end. That said, i think i > found another metaphor that summarizes the notion for me. In the same way > that the group axioms organize notions of symmetry, including addition, > multiplication, reflections, translations, rotations, ... the monad(ic > axioms) organize(s) notions of snapshot (return) and update (bind), > including state, i/o, control, .... In short > > group : symmetry :: monad : update > > Best wishes, > > --greg > > -- > L.G. Meredith > Managing Partner > Biosimilarity LLC > 505 N 72nd St > Seattle, WA 98103 > > +1 206.650.3740 > > http://biosimilarity.blogspot.com -- L.G. Meredith Managing Partner Biosimilarity LLC 505 N 72nd St Seattle, WA 98103 +1 206.650.3740 http://biosimilarity.blogspot.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/412c87a9/attachment-0001.htm From haskell at list.mightyreason.com Wed Aug 1 15:23:58 2007 From: haskell at list.mightyreason.com (ChrisK) Date: Wed Aug 1 15:16:38 2007 Subject: [Haskell-cafe] Re: Knuth Morris Pratt for Lazy Bytestrings implementation In-Reply-To: References: <20070801020709.GF21697@cse.unsw.EDU.AU> Message-ID: <46B0DDCE.4040704@list.mightyreason.com> I am still working on improving your code. And I have a "Is this a bug?" question: The "lookup = computeLookup pat" defines lookup to take an Int which represents the index into pat, where this index is 0 based and the 0th item is the head of pat. Now look at "matchLength :: Int; matchLength = let ... in matchLength' (B.drop (fromIntegral patShift) pat) str 0" That starts the "pat" from a shorter version that starts at 'patShift' and sets the last argument to matchLength' to 0. matchLength' is in the ... as: let matchLength' pat str cnt | B.null pat = cnt matchLength' pat str cnt | B.null str = 0 matchLength' pat str cnt | (B.head pat == B.head str) = matchLength' (B.drop 1 pat) (B.drop 1 str) (cnt + 1) | otherwise = cnt I see that cnt is incremented until * all of pat is matched, return cnt * all of str is used, return 0 * a mismatch is found, return cnt So a mismatch means that the character at index (patShift+cnt) in the original 'pat' had the mismatch. Now I see this that uses the 'cnt' returned from matchLength: shiftAmt = {-# SCC "kmpMatch_shiftAmt" #-} lookup matchLength And this is the bug. lookup should be given (shiftAmt + matchLength). This was not clear or obvious since * Nearly everything is Int or Int64 * The name "pat" in matchLength' shadows "pat" in kmpMatch This was not caught by quickcheck since it is an internal value and only rarely will trigger an error where a legitimate match is missed. If there is no match then this bug does not cause an incorrect answer (I think). I will fix this and continue hacking on it. -- Chris From ryani.spam at gmail.com Wed Aug 1 15:31:43 2007 From: ryani.spam at gmail.com (Ryan Ingram) Date: Wed Aug 1 15:24:02 2007 Subject: [Haskell-cafe] How can I optimize pattern matching on views? Message-ID: <2f9b2d30708011231m5d45e854s77b1de2fe18ac3ba@mail.gmail.com> Background: I participated in this year's ICFP programming contestand our team did quite well, coming in 37th. Our simulator (in somewhat naive C++ with a good algorithm) took about 45 seconds to run the original problem, and afterwards one of my coworkers took the same algorithm and optimized it to run in about 6-10 seconds. The rest of the email will have minor spoilers, so skip it if you want to work on the problem yourself. I'm using that problem as a good testcase for learning to write high-performance Haskell. I'm using the same data structure and basic algorithm as the C++ version, but I'm having problems getting the performance where I think it should be. The relevant parts of the code: > import qualified Data.ByteString.Base as B > import qualified Data.ByteString.Char8 as BC > > type DNABlock = B.ByteString > type DNA = [DNABlock] I represent the DNA string as a simplified ropethat supports fast reading from the front & prepending. To access this in a reasonable fashion, I used a view to let me treat the data as a string. Here's a sample bit of code using that view: > matchConsts :: Int -> DNA -> (Int, DNA) > matchConsts len dna | len `seq` dna `seq` False = undefined -- force strictness > matchConsts len dna = case dnaView dna of > ('F':_) -> matchConsts (len+1) (dropDna 1 dna) > ('C':_) -> matchConsts (len+1) (dropDna 1 dna) > ('P':_) -> matchConsts (len+1) (dropDna 1 dna) > ('I':'C':_) -> matchConsts (len+2) (dropDna 2 dna) > _ -> (len, dna) > dropDna :: Int -> DNA -> DNA > dropDna n dna | n `seq` dna `seq` False = undefined -- force strictness > dropDna _ [] = [] > dropDna 0 dna = d > dropDna n (d:ds) > | n >= BC.length d = dropDna (n - BC.length d) ds > | otherwise = B.unsafeDrop n d : ds > {-# INLINE dropDna #-} Profiling showed that almost all of my time & allocations were spent in my view function: > dnaView :: DNA -> String > -- dnaView d = foldr (++) [] (map BC.unpack d) > -- This was ridiculously slow for some reason that I don't entirely understand > dnaView [] = [] > dnaView (d:ds) > | BC.null d = dnaView ds > | otherwise = (w2c $ B.unsafeHead d) : dnaView (B.unsafeTail d : ds) > {-# INLINE dnaView #-} The question I have for you, the haskell-cafe-reading-audience, is how can I get GHC to do smart code-gen for this? I want "case dnaView dna of ..." to not allocate and instead fuse the list generation with the pattern-match. -- ryan -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/67753f53/attachment.htm From alex at alexjacobson.com Wed Aug 1 15:32:54 2007 From: alex at alexjacobson.com (Alex Jacobson) Date: Wed Aug 1 15:25:39 2007 Subject: [Haskell-cafe] OS swapping and haskell data structures In-Reply-To: <1185993632.5989.79.camel@localhost> References: <46B01E14.2020109@alexjacobson.com> <46B0D198.2040506@serpentine.com> <1185993632.5989.79.camel@localhost> Message-ID: <46B0DFE6.5080008@alexjacobson.com> Ok, so for low throughput applications, you actually need a disk strategy. Got it. Ok, is there a standard interface to BerkleyDB or some other disk based store? -Alex- Duncan Coutts wrote: > On Wed, 2007-08-01 at 11:31 -0700, Bryan O'Sullivan wrote: >> Alex Jacobson wrote: >>> If you create a Data.Map or Data.Set larger than fits in physical >>> memory, will OS level swapping enable your app to behave reasonably or >>> will things just die catastrophically as you hit a memory limit? >> Relying on the OS to page portions of your app in and out should always >> be the fallback of last resort. You are fairly guaranteed to get >> terrible performance because the VM subsystem can't anticipate your >> app's memory access patterns, and catastrophic death of either your app >> or other system processes is a strong possibility (Google for "OOM >> killer" if you want some horror stories). In many cases, you can't even >> rely on paging being possible. > > Furthermore, as I understand it, GC does not interact well with paging > since the GC has to traverse the data structures on major GCs it'll > force it all to be kept in memory. > > Duncan From sethg at ropine.com Wed Aug 1 15:37:37 2007 From: sethg at ropine.com (Seth Gordon) Date: Wed Aug 1 15:30:09 2007 Subject: [Haskell-cafe] OS swapping and haskell data structures In-Reply-To: <46B0DFE6.5080008@alexjacobson.com> References: <46B01E14.2020109@alexjacobson.com> <46B0D198.2040506@serpentine.com> <1185993632.5989.79.camel@localhost> <46B0DFE6.5080008@alexjacobson.com> Message-ID: <46B0E101.4010008@ropine.com> Alex Jacobson wrote: > Ok, so for low throughput applications, you actually need a disk > strategy. Got it. > > Ok, is there a standard interface to BerkleyDB or some other disk based > store? I would absolutely kvell if there were some way to use a disk-based store to back Haskell objects without going through the IO monad. From westondan at imageworks.com Wed Aug 1 16:01:36 2007 From: westondan at imageworks.com (Dan Weston) Date: Wed Aug 1 15:53:58 2007 Subject: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <00d401c7d447$fe1c1bd0$fa545370$@be> References: <00d401c7d447$fe1c1bd0$fa545370$@be> Message-ID: <46B0E6A0.3010707@imageworks.com> Here's my rant about the way monads are explained in Haskell tutorials (which are much too polluted with nuclear waste to be safely approached): It is a big mistake to start with the IO monad. It pollutes and misdirects the understanding of what a monad is. The dreaded "nuclear waste" metaphor is actually a red herring, having nothing do do with a monad at all, merely the artifact of the absence of an exit function in the IO monad (which actually does exist and is called unsafePerformIO, but that is a secret. Shhh...), combined with Haskell's refusal to work for free. Monads are required to have an extrance (reification/constructor function) called return. They are *not* required to have an exit (reflection/deconstructor function). They *do* combine (bind) together like links in a chain, which is not a list but an equivalence class of trees, where the only thing that matters is the order of the leaves, so unlike a list you don't have to start at the tail and assemble one-by-one. [Actually, the compiler picks just one of these trees (the singly-linked list) but expects that all trees would evaluate the same.] They *do* bind only with flavors of themselves (State a cannot bind to IO b, though a monad transformer can merge the two). The output type of one monad instance must match the input type of another monad reification function (e.g. return) that it wants to bind to. In compensation for this tribalism, those snobby monads that want to clique off are out of luck: a monad cannot restrict what possible types can be used to construct a monad instance. That would be discrimination, and you must agree to accept all comers. Simple, no? Apparently not... Other things have nothing to do with monads per se gunk up the descriptions about monads: One red herring (the nuclear waste metaphor) refers to the fact since monads may or may not have an escape-clause (called variously runXXX, evalXXX, unsafePerformXXX), and IO in particular does not. The presence or absence of this has *nothing* to do with monads (only with IO), participates in no monadic laws, and shouldn't even be in the chapter on Monads. Whether nuclear waste seeps in (as in a State monad) or stays out (IO monad) has nothing to do with their monadic property and is a special property of those particular classes. Another even redder herring is the dreaded sequencing aspect. Monads do sequence *denotationally*, the way any nested closures sequence, which is exactly *backwards* from the naive understanding of sequencing: symbols defined to the left are in the *inner* scope, those to the right are in the *outer* scope. Perversely, when the symbols are evaluated, the rightmost monad is evaluated first. The leftmost monad in the program, the IO () passed in by main, is the *last* thing to be evaluated, not the first. The outermost monad (rightmost bound function) is in the driver seat, and is absolutely free to ignore the monad to its left (which in turn encloses monads to its left)! This includes of course the main input IO () monad. Don't believe me? Prelude> const 3 (return "Nuclear waste leaking..." >>= print) + 5 8 Phew, no nuclear waste leaked after all. What a relief! This sequencing then has nothing to do with *operational* sequencing. When the symbols are evaluated is the basic call-by-need data-dependent stuff of most Haskell symbols and again, has nothing to do with monads. I learned about the IO monad first and I regret it bitterly. It cost me a years' worth of misunderstanding. I misapprehended that a monad had something to do with nuclear waste and never escaping the single-threadedness. I hope the new O'Reilly book doesn't make that mistake. Teach IO right away, but just don't call it a monad. IO is the exception, not the rule, in the menagerie of Haskell monads. How does all this map to C++? A monad is a a class, with no useful interface for the end user, that looks roughly (i.e. I haven't tested it) like: template class Monad { public: virtual ~Monad() {} // return Monad(T t) : t_(t) {} // bind operator (>>=), where // F :: Monad -> (T -> Monad) -> Monad virtual template Monad operator>>(typename U::F f) = 0; private: T t_; }; C++ programmers will immediately see past the syntactic kruft to notice that 1) the constructor arg is not a value but an unevaluated function object, that starts out unevaluated. 2) The result of m >> f is a monad object, totally unevaluated. 3) There is no member function to do anything with the monad at all! As is, it is useless. Derivers of this class will naturally want to add such functionality: template class MyMonad : public Monad { // The parent class needs to know what type of monad // this can bind to typedef someUnaryFunctionObjectTypeReturningB F; // There is no input, just an output! // The input is via the constructor arg of the innermost monad B operator()() { ... start the ball rolling ... } }; Non-C++ programmers will be stunned that the above garbage can be understood by anyone, compared to the simplicity of type classes in Haskell. When all you have is a hammer... The moral of the story is that monads are less than meets the eye. You can create them and concatenate them, but may not be able to do anything with them (some monads do let you, some don't), though the runtime system agrees to evaluate one special monad exactly once. What the rightmost monad does with its internals (including all inner/left monads bound to it) has nothing to do with monads whatever, except for the minimal requirement that they agree to be bound only to other monads like themselves, and that as a group they all agree to not form a clique (i.e. they are associative). What could be simpler that that? No please, no more nuclear waste! :) Dan peterv wrote: > Kaveh> "A monad is like a loop that can run a new function against its variable in each iteration." > > I?m an imperative programmer learning Haskell, so I?m a newbie, but I?ll give it a try ? Making mistakes is the best way to learn it ;) > > There are lots of different kinds of monads, but let?s stick to the IO monad first, which you seem to refer to. > > No *an IO monad is not a loop at all*. Instead, from an imperative programmer?s point of view, the following might be better: > > ?an IO monad is a delayed action that will be executed as soon as that action is needed for further evaluation of the program.? > > The simple program > > main = getLine >>= putStrLn > > can be visually represented as (see attachment) > > The ?world? (=a representation of your computer?s hardware) is passed to the main function, which passes it to all actions that it encounters during its lazy evaluation, causing the executing of the actions as an effect. > > The red wire through which the ?world flows? is a ?single thread?, it cannot be split (because the physical world cannot be copied!!!), so no unwanted side effects can ever occur, making IO safe in Haskell. > > When you write your IO program, this world object is never available (the IO type is a special internal type), so the red wire is erased from the diagram, and the getLine and putStrLn boxes become ?delayed actions?. > > Imperative programmers like myself might initially be confused when they see Haskell?s do notation, because it looks like the actions are strict statements as in C/C++/Pascal/Java/C#/etc, but they are not. > > For example, try the following program: > > main = do last [ > putStrLn "NOT executed although it is first in the list, as it is not used by the main function!", > putStrLn "This action IS executed because it is evaluated by the main function." ] > > This is of course all due to Haskell?s laziness which only evaluates just those expressions that it needs to evaluate the main function. > > One thing to note in the diagram above is that the getLine box has TWO outputs, the String and the World. But functions can only have a single output, but this can be tuple. Hence the passing of the world from one box to the other is a bit more complicated. It is this pattern of extracting both values from the output and passing them to the next function and other related combinations that form the generic monad class, which can be used for many more things than IO. > > See http://haskell.org/haskellwiki/IO_inside for a much deeper and more correct explanation ? > > And for the pros here, did this newbie make any sense? Probably not ;-) > > Oh no, yet another monad explanation!!! Now the universe will most certainly collapse? > > > No virus found in this outgoing message. > Checked by AVG Free Edition. > Version: 7.5.476 / Virus Database: 269.11.0/929 - Release Date: 31/07/2007 17:26 > > > > > ------------------------------------------------------------------------ > > > ------------------------------------------------------------------------ > > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe From duncan.coutts at worc.ox.ac.uk Wed Aug 1 16:09:13 2007 From: duncan.coutts at worc.ox.ac.uk (Duncan Coutts) Date: Wed Aug 1 16:00:29 2007 Subject: [Haskell-cafe] OS swapping and haskell data structures In-Reply-To: <46B0DFE6.5080008@alexjacobson.com> References: <46B01E14.2020109@alexjacobson.com> <46B0D198.2040506@serpentine.com> <1185993632.5989.79.camel@localhost> <46B0DFE6.5080008@alexjacobson.com> Message-ID: <1185998953.5989.83.camel@localhost> On Wed, 2007-08-01 at 12:32 -0700, Alex Jacobson wrote: > Ok, so for low throughput applications, you actually need a disk > strategy. Got it. > > Ok, is there a standard interface to BerkleyDB or some other disk based > store? Well on hackage there's anydbm and BerkeleyDB. The former is probably the older and more mature of the two. Duncan From fb at frank-buss.de Wed Aug 1 16:27:31 2007 From: fb at frank-buss.de (Frank Buss) Date: Wed Aug 1 16:19:54 2007 Subject: RE [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <46B0E6A0.3010707@imageworks.com> References: <00d401c7d447$fe1c1bd0$fa545370$@be> <46B0E6A0.3010707@imageworks.com> Message-ID: <063901c7d47a$633f2610$64c5a8c0@galilei> > How does all this map to C++? A monad is a a class, with no useful > interface for the end user, that looks roughly (i.e. I haven't tested > it) like: trying to implement it in other languages is a good idea for understanding monads. I've tried this with the Maybe monad in Lisp: http://groups.google.com/group/comp.lang.lisp/msg/3bd8ecfb6cfd6601 There are other tries in Scheme and Lisp, even a general Arrows approach IIRC. -- Frank Buss, fb@frank-buss.de http://www.frank-buss.de, http://www.it4-systems.de From westondan at imageworks.com Wed Aug 1 16:32:53 2007 From: westondan at imageworks.com (Dan Weston) Date: Wed Aug 1 16:25:14 2007 Subject: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer In-Reply-To: <46B0E6A0.3010707@imageworks.com> References: <00d401c7d447$fe1c1bd0$fa545370$@be> <46B0E6A0.3010707@imageworks.com> Message-ID: <46B0EDF5.4020304@imageworks.com> > The outermost monad (rightmost bound function) is in the driver seat, and is absolutely free to ignore the monad to its > left (which in turn encloses monads to its left)! This includes of > course the main input IO () monad. Don't believe me? > > Prelude> const 3 (return "Nuclear waste leaking..." >>= print) + 5 > 8 > > Phew, no nuclear waste leaked after all. What a relief! No, I don't believe you. It's true that the right monad instance can ignore its left sibling (same monad of course, just a different instance) to allow backtracking (the Const monad being a trivial example of this), but IO is not such a monad. Your example just shows that monad instance expressions (like any Haskell expression) are evaluated lazily in Haskell. I am relieved though, that no nuclear waste was leaked by your example. Dan Weston wrote: > Here's my rant about the way monads are explained in Haskell tutorials > (which are much too polluted with nuclear waste to be safely approached): > > It is a big mistake to start with the IO monad. It pollutes and > misdirects the understanding of what a monad is. The dreaded "nuclear > waste" metaphor is actually a red herring, having nothing do do with a > monad at all, merely the artifact of the absence of an exit function in > the IO monad (which actually does exist and is called unsafePerformIO, > but that is a secret. Shhh...), combined with Haskell's refusal to work > for free. > > Monads are required to have an extrance (reification/constructor > function) called return. They are *not* required to have an exit > (reflection/deconstructor function). > > They *do* combine (bind) together like links in a chain, which is not a > list but an equivalence class of trees, where the only thing that > matters is the order of the leaves, so unlike a list you don't have to > start at the tail and assemble one-by-one. [Actually, the compiler picks > just one of these trees (the singly-linked list) but expects that all > trees would evaluate the same.] > > They *do* bind only with flavors of themselves (State a cannot bind to > IO b, though a monad transformer can merge the two). The output type of > one monad instance must match the input type of another monad > reification function (e.g. return) that it wants to bind to. > > In compensation for this tribalism, those snobby monads that want to > clique off are out of luck: a monad cannot restrict what possible types > can be used to construct a monad instance. That would be discrimination, > and you must agree to accept all comers. > > Simple, no? Apparently not... > > Other things have nothing to do with monads per se gunk up the > descriptions about monads: > > One red herring (the nuclear waste metaphor) refers to the fact since > monads may or may not have an escape-clause (called variously runXXX, > evalXXX, unsafePerformXXX), and IO in particular does not. The presence > or absence of this has *nothing* to do with monads (only with IO), > participates in no monadic laws, and shouldn't even be in the chapter on > Monads. Whether nuclear waste seeps in (as in a State monad) or stays > out (IO monad) has nothing to do with their monadic property and is a > special property of those particular classes. > > Another even redder herring is the dreaded sequencing aspect. Monads do > sequence *denotationally*, the way any nested closures sequence, which > is exactly *backwards* from the naive understanding of sequencing: > symbols defined to the left are in the *inner* scope, those to the right > are in the *outer* scope. Perversely, when the symbols are evaluated, > the rightmost monad is evaluated first. The leftmost monad in the > program, the IO () passed in by main, is the *last* thing to be > evaluated, not the first. The outermost monad (rightmost bound function) > is in the driver seat, and is absolutely free to ignore the monad to its > left (which in turn encloses monads to its left)! This includes of > course the main input IO () monad. Don't believe me? > > Prelude> const 3 (return "Nuclear waste leaking..." >>= print) + 5 > 8 > > Phew, no nuclear waste leaked after all. What a relief! > > This sequencing then has nothing to do with *operational* sequencing. > When the symbols are evaluated is the basic call-by-need data-dependent > stuff of most Haskell symbols and again, has nothing to do with monads. > > I learned about the IO monad first and I regret it bitterly. It cost me > a years' worth of misunderstanding. I misapprehended that a monad had > something to do with nuclear waste and never escaping the > single-threadedness. I hope the new O'Reilly book doesn't make that > mistake. Teach IO right away, but just don't call it a monad. IO is the > exception, not the rule, in the menagerie of Haskell monads. > > How does all this map to C++? A monad is a a class, with no useful > interface for the end user, that looks roughly (i.e. I haven't tested > it) like: > > template > class Monad > { > public: > > virtual ~Monad() {} > > // return > Monad(T t) : t_(t) {} > > // bind operator (>>=), where > // F :: Monad -> (T -> Monad) -> Monad > virtual template Monad > operator>>(typename U::F f) = 0; > > private: > T t_; > }; > > C++ programmers will immediately see past the syntactic kruft to notice > that > 1) the constructor arg is not a value but an unevaluated function > object, that starts out unevaluated. > 2) The result of m >> f is a monad object, totally unevaluated. > 3) There is no member function to do anything with the monad at all! As > is, it is useless. > > Derivers of this class will naturally want to add such functionality: > > template > class MyMonad : public Monad > { > // The parent class needs to know what type of monad > // this can bind to > typedef someUnaryFunctionObjectTypeReturningB F; > > // There is no input, just an output! > // The input is via the constructor arg of the innermost monad > B operator()() { ... start the ball rolling ... } > }; > > Non-C++ programmers will be stunned that the above garbage can be > understood by anyone, compared to the simplicity of type classes in > Haskell. When all you have is a hammer... > > The moral of the story is that monads are less than meets the eye. You > can create them and concatenate them, but may not be able to do anything > with them (some monads do let you, some don't), though the runtime > system agrees to evaluate one special monad exactly once. > > What the rightmost monad does with its internals (including all > inner/left monads bound to it) has nothing to do with monads whatever, > except for the minimal requirement that they agree to be bound only to > other monads like themselves, and that as a group they all agree to not > form a clique (i.e. they are associative). > > What could be simpler that that? No please, no more nuclear waste! :) > > Dan > > peterv wrote: >> Kaveh> "A monad is like a loop that can run a new function against its >> variable in each iteration." >> I?m an imperative programmer learning Haskell, so I?m a newbie, but >> I?ll give it a try ? Making mistakes is the best way to learn it ;) >> >> There are lots of different kinds of monads, but let?s stick to the IO >> monad first, which you seem to refer to. >> >> No *an IO monad is not a loop at all*. Instead, from an imperative >> programmer?s point of view, the following might be better: >> >> ?an IO monad is a delayed action that will be executed as soon as that >> action is needed for further evaluation of the program.? >> >> The simple program >> >> main = getLine >>= putStrLn >> can be visually represented as (see attachment) >> >> The ?world? (=a representation of your computer?s hardware) is passed >> to the main function, which passes it to all actions that it >> encounters during its lazy evaluation, causing the executing of the >> actions as an effect. >> The red wire through which the ?world flows? is a ?single thread?, it >> cannot be split (because the physical world cannot be copied!!!), so >> no unwanted side effects can ever occur, making IO safe in Haskell. >> When you write your IO program, this world object is never available >> (the IO type is a special internal type), so the red wire is erased >> from the diagram, and the getLine and putStrLn boxes become ?delayed >> actions?. >> Imperative programmers like myself might initially be confused when >> they see Haskell?s do notation, because it looks like the actions are >> strict statements as in C/C++/Pascal/Java/C#/etc, but they are not. >> >> For example, try the following program: >> >> main = do last [ >> putStrLn "NOT executed although it is first in the list, as >> it is not used by the main function!", >> putStrLn "This action IS executed because it is evaluated >> by the main function." ] >> >> This is of course all due to Haskell?s laziness which only evaluates >> just those expressions that it needs to evaluate the main function. >> >> One thing to note in the diagram above is that the getLine box has TWO >> outputs, the String and the World. But functions can only have a >> single output, but this can be tuple. Hence the passing of the world >> from one box to the other is a bit more complicated. It is this >> pattern of extracting both values from the output and passing them to >> the next function and other related combinations that form the generic >> monad class, which can be used for many more things than IO. >> >> See http://haskell.org/haskellwiki/IO_inside for a much deeper and >> more correct explanation ? >> >> And for the pros here, did this newbie make any sense? Probably not ;-) >> Oh no, yet another monad explanation!!! Now the universe will most >> certainly collapse? >> >> No virus found in this outgoing message. >> Checked by AVG Free Edition. Version: 7.5.476 / Virus Database: >> 269.11.0/929 - Release Date: 31/07/2007 17:26 >> >> >> >> ------------------------------------------------------------------------ >> >> >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> Haskell-Cafe mailing list >> Haskell-Cafe@haskell.org >> http://www.haskell.org/mailman/listinfo/haskell-cafe > > From westondan at imageworks.com Wed Aug 1 16:42:52 2007 From: westondan at imageworks.com (Dan Weston) Date: Wed Aug 1 16:35:16 2007 Subject: [Haskell-cafe] Cartesian product of a Set In-Reply-To: <20070801142801.GA7647@cspcag2.swan.ac.uk> References: <20070801142801.GA7647@cspcag2.swan.ac.uk> Message-ID: <46B0F04C.1090604@imageworks.com> Andy Gimblett wrote: > Hi all, > > Is this a reasonable way to compute the cartesian product of a Set? > >> cartesian :: Ord a => S.Set a -> S.Set (a,a) >> cartesian x = S.fromList [(i,j) | i <- xs, j <- xs] >> where xs = S.toList x > > It's a fairly "obvious" way to do it, but I wondered if there were any > hidden gotchas. I'm particularly concerned by toList (O(n)) fromList > (O(n log n)) - but for other reasons I'd really like to be using Set > rather than List for this (I think). > > Many thanks for any thoughts, > > -Andy > Your list comprehension always generates a sorted list, so changing S.fromList to its "unsafe" version (but guarateed by you) S.fromDistinctAscList should get you back to O(n). Of course the order of the generators was key (i before j). Dan From feeder.of.the.bears at gmail.com Wed Aug 1 16:48:07 2007 From: feeder.of.the.bears at gmail.com (David Pollak) Date: Wed Aug 1 16:40:27 2007 Subject: [Haskell-cafe] Some Haskell platformish questions Message-ID: Howdy, I'm considering building a desktop app using Haskell. The primary target for the app is Windows, but if it runs on Linux and Mac (Intel and PPC), that'd be a bonus. I've got a bunch of questions that hopefully folks can answer. Well, before I start, you might well be asking "Gee David, you're a Scala kind of guy... I mean, you're the primary contributor to lift... why not use Scala?" Well, I'm looking to build something that compiles down to native code and has a smaller download (and runtime) footprint than the JVM offers. I've come to love functional programming and am taking the current side project as an opportunity to learn Haskell. So... on to the questions: - Can GHC generate stand-alone executables with all the dependencies linked in such that I can distribute the single file without worrying about including a bunch of DLLs/SOs? The answer seems to be yes, but I wanted to confirm. - How much of a distribution footprint is the Haskell runtime? If I have a "Hello World" app, roughly how big will the EXE be (if one includes the JRE in the runtime, a Java/Scala program has a minimum footprint of 20M... that's big.) - Same goes for the runtime... I've looked at the stats on the Language Shootout home page and these look encouraging, but I wanted to see if the reasonable footprint is a reality. - How real/solid/stable is the wxHaskell widgets package? Is it being well maintained? Is there (okay... this is pie in the sky) an GUI Builder for it? - How are the Windows/COM bindings in Haskell... would it be possible to, for example, embed an IE Browser COM control in a a wxHaskell window? - I found a package to do HTTP requests in Haskell but it does not seem to support HTTPS. Is there an HTTPS client package for Haskell? - How are Strings internally represented? Are they single byte or multi-byte characters? How easy it is to translate to/from internal representation to UTF-8? - How's the XML support? Will the XML parser handle non-Latin characters and properly encode stuff? Does XML get parsed down into easily mappable/filterable collections? - Is there support for SHA256 (I saw an SSLeay package which had support for a lot of stuff, but not SHA256)? - I understand that Haskell has "a better approach" to parallelizing tasks, but I have not seen much about the actual manifestation of this... would someone be so kind as to give me a pointer? - On a related note, I have become a fan (via Scala) of Erlang-style Actors and asynchronous message passing. Are there any similar packages for Haskell? - I tend to do most of my coding in either Emacs or Eclipse... how's the Haskell support in either? Is there a preferred editor (I don't mean to start any wars here... :-) - Are there any production Haskell-based desktop apps of note? Anyway... sorry for the long list of questions. I look forward to hearing from you all and learning more about Haskell. Thanks, David -- lift, the fast, powerful, easy web framework http://liftweb.net -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070801/29d447b3/attachment-0001.htm From dm.maillists at gmail.com Wed Aug 1 16:51:26 2007 From: dm.maillists at gmail.com (Daniel McAllansmith) Date: Wed Aug 1 16:43:47 2007 Subject: [Haskell-cafe] Backpatching In-Reply-To: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> References: <784a62100707312244gaaf478i41dba90d9b86dcd1@mail.gmail.com> Message-ID: <200708020851.26324.dm.maillists@gmail.com> On Wednesday 01 August 2007 17:44, Thomas Conway wrote: > This sounds like a common problem type. Is there a well known solution > to this sort of problem? Have you looked into Tying the Knot? http://www.haskell.org/haskellwiki/Tying_the_Knot A simple example: module Knot where import Data.Char import Data.Maybe type Input = String type Output = [(Char, Int)] type Resolver = (Char -> Int) resolvingError c = error ("Couldn't resolve: " ++ [c]) parseInput :: Resolver -> Input -> Output parseInput _ [] = [] parseInput resolve (c:cs) | isUpper c = ((c, fromEnum c) : parseInput f cs) | otherwise = ((c, resolve c) : parseInput f cs) makeResolver :: Output -> Resolver makeResolver o c = fromMaybe (resolvingError c) (lookup (toUpper c) o) foo :: Input -> Output foo i = let o = parseInput (makeResolver o) i in o testGood = foo "CaBcbA" testBad = foo "CaBcb" From haskell at list.mightyreason.com Wed Aug 1 16:54:56 2007 From: haskell at list.mightyreason.com (ChrisK) Date: Wed Aug 1 16:47:41 2007 Subject: [Haskell-cafe] Re: Knuth Morris Pratt for Lazy Bytestrings implementation In-Reply-To: <46B0CB29.5080101@list.mightyreason.com> References: <20070801020709.GF21697@cse.unsw.EDU.AU> <46B0CB29.5080101@list.mightyreason.com> Message-ID: <46B0F320.7090600@list.mightyreason.com> My optimized (and fixed) version of the code is attached. I benchmarked it with: > module Main(main) where > import KMPSeq > import qualified Data.ByteString.Lazy as B > import qualified Data.ByteString.Lazy.Char8 as BC > infile = "endo.dna" Modified by one character from the original copied from the endo.dna The leading "IIIII" is often overlapping with the suffix of a prefix of substring so KMP should help here > substring1 = BC.pack "IIIIIPIIIPIIIIIPIIIPFFICCPIIIPFFFFFPIIIPFFFFFPIIIPIIFIIPIIIPIIIIIPIIIPIIIIIPIIIPIIIIIPIIIPCCCCCPI" original "IIIIIPIIIPIIIIIPIIIPFFICCPIIIPFFFFFPIIIPFFFFFPIIIPIIIIIPIIIPIIIIIPIIIPIIIIIPIIIPIIIIIPIIIPCCCCCPI" > getSearch = do > B.readFile infile > main :: IO () > main = do > print . kmpMatch substring1 =<< getSearch The bug fix is actually a big speed win for this benchmark. The long commentary I wrote has been sent to Justin Bailey with each step I took and each measurement I made. (800 lines with all the pasted profiles). The speedup was from 18.5 seconds to 2.6 seconds on the above benchmark. Cheers, Chris Kuklewicz >From Martin Amis' short story "The Janitor on Mars": "...The War with the Scythers of the Orion Spur was hotly prosecuted for just over a billion years. Who won? We did. They're still there, the Scythers. Their planet is still there. The nature of war changed, during that trillennium. It was no longer nuclear or quantum-gravitational. It was neurological. Informational. Life goes on for the Scythers, but its quality has been subtly reduced. We fixed it so that they think they're simulations in a deterministic computer universe. It is believed that this is the maximum suffering you can visit on a type-v world." http://www.metafilter.com/mefi/18176 -------------- next part -------------- -- Code by Justin Bailey with optimizations by Chris Kuklewicz {-# OPTIONS_GHC -fbang-patterns #-} module KMPSeq (kmpMatch) where import qualified Data.Array.Base as Base (unsafeAt) import qualified Data.Array.Unboxed as Unboxed (UArray) import qualified Data.Array.IArray as IArray ((!), Array, array) import Data.List as List (map, filter, length, null, take, maximum, foldr, all, drop) import qualified Data.ByteString.Lazy as B import qualified Data.ByteString as S import qualified Data.ByteString.Base as B (unsafeHead,unsafeTail,unsafeDrop,unsafeIndex) import GHC.Int (Int64) import Test.QuickCheck import Data.ByteString as S (isSubstringOf, pack, ByteString) -- Only used during testing import Debug.Trace (trace) import System.IO.Unsafe import System.IO {- Returns the first index for which the pattern given is found in the string given, or -1 if the pattern does not appear. -} kmpMatch :: B.ByteString -- ^ The pattern -> B.ByteString -- ^ The string to search -> Int64 -- ^ Result kmpMatch patLazy search | B.null patLazy = 0 -- Empty pattern matches right away. | otherwise = let pat :: S.ByteString pat = S.concat (B.toChunks patLazy) lookupTable = computeLookupS pat patLen = fromIntegral $ S.length pat -- currPatIdx is our position in the pattern - sometimes we don't -- have to match the whole pattern again. -- -- currIdx is our position in the string. We B.drop elements from str -- on each iteration so have to track our position separately. kmpMatch' :: B.ByteString -> Int64 -> Int -> Int64 kmpMatch' !str !currIdx !patShift | B.null str = -1 | otherwise = -- Find length of prefix in our pattern which matches string (possibly zero) let matchLength :: Int matchLength = let matchLength' :: B.ByteString -> Int -> Int matchLength' !str !cnt | cnt == patLen = patLen | B.null str = 0 | B.unsafeIndex pat cnt == B.head str = matchLength' (B.tail str) (succ cnt) | otherwise = cnt in matchLength' str patShift shiftAmt = Base.unsafeAt lookupTable matchLength {-# INLINE matchLen64 #-} matchLen64 = fromIntegral (matchLength-patShift) in case matchLength of _ | matchLength == patLen -> currIdx - fromIntegral patShift -- found complete match | matchLength == patShift -> kmpMatch' (B.tail str) (currIdx + 1) 0 | shiftAmt > 0 -> kmpMatch' (B.drop matchLen64 str) (currIdx + matchLen64) shiftAmt | otherwise -> kmpMatch' (B.drop matchLen64 str) (currIdx + matchLen64) patShift in kmpMatch' search 0 0 -- These tests have failed in the past -- kmpMatch (toLazyBS "ccb") (toLazyBS "abcdcccb") == 5 -- kmpMatch (toLazyBS "bbaa") (toLazyBS "bdcdbbbbaa") == 6 -- kmpMatch (toLazyBS "cccadadc") (toLazyBS "adaccccadadc") == 4 -- This next one has caused an infinite loop previously. -- kmpMatch (toLazyBS "bbbb") (toLazyBS "dddcaaaddaaabdacbcccabbada") {-| Given our pattern, get all the prefixes of the pattern. For each of those prefixes, find the longest prefix from the original pattern that is also a suffix of the prefix segment being considered, and is not equal to it. The argument given to overlap is the length of the prefix matched so far, and the length of the longest prefix, which is a suffix and is not equal to it, is the value overlap returns. If a given prefix has no possible overlap, it is mapped to -1. -} overlap :: S.ByteString -> [(Int, Int)] overlap pat = let patternLength = S.length pat -- Necessary to reverse prefixes since 'isSuffixOf' not implemented for lazy bytestrings. prefixes = List.map S.reverse $ List.take (fromIntegral patternLength) $ S.inits pat longestPreSuffix prefix = -- Find prefixes that are a prefix of this suffix, but -- are not equal to it. let suffixes = List.filter (\p -> p `S.isPrefixOf` prefix && p /= prefix) prefixes in if S.null prefix || List.null suffixes then 0 else List.maximum (List.map S.length suffixes) in List.map (\prefix -> (fromIntegral $ S.length prefix, fromIntegral $longestPreSuffix prefix)) prefixes {- | Given a string representing a search pattern, this function returns a function which represents, for each prefix of that pattern, the maximally long prefix of the pattern which is a suffix of the indicated pattern segment. If there is no such prefix, 0 is returned. -} computeLookupS :: S.ByteString -> Unboxed.UArray Int Int computeLookupS pat = let patLen = fromIntegral $ S.length pat table :: Unboxed.UArray Int Int table = {-# SCC "computeLookup_table" #-} IArray.array (0, patLen - 1) (overlap pat) in table computeLookup :: B.ByteString -> (Int -> Int) computeLookup pat = let patLen = fromIntegral $ B.length pat table :: Unboxed.UArray Int Int table = {-# SCC "computeLookup_table" #-} IArray.array (0, patLen - 1) (overlap . S.concat . B.toChunks $ pat) in Base.unsafeAt table -- Types, instances and utility functions for testing purposes. newtype PatternChar = PatternChar Char deriving Show instance Arbitrary PatternChar where arbitrary = oneof (List.map (return . PatternChar) ['a', 'b', 'c', 'd']) patternsToString :: [PatternChar] -> B.ByteString patternsToString chars = B.pack $ List.foldr (\(PatternChar char) str -> (toEnum $ fromEnum char) : str) [] chars patternsToStrictString :: [PatternChar] -> S.ByteString patternsToStrictString chars = S.pack $ List.foldr (\(PatternChar char) str -> (toEnum $ fromEnum char) : str) [] chars toLazyBS :: String -> B.ByteString toLazyBS = B.pack . List.map (toEnum . fromEnum) toStrictBS :: String -> S.ByteString toStrictBS = S.pack . List.map (toEnum . fromEnum) -- Test that 0 and 1 element always return 0, if present. prop_testZero :: [PatternChar] -> Property prop_testZero pat = let lookup = computeLookup (patternsToString pat) in not (List.null pat) ==> if List.length pat > 1 then lookup 0 == 0 && lookup 1 == 0 else lookup 0 == 0 -- Test that all overlaps found are actually prefixes of the -- pattern string prop_testSubset :: [PatternChar] -> Property prop_testSubset pat = let patStr = patternsToString pat lookup = computeLookup patStr prefix len = B.take (fromIntegral len) testPrefix len = if lookup len == 0 then True else (prefix (lookup len) patStr) `B.isPrefixOf` (prefix len patStr) in not (List.null pat) ==> trivial (B.null patStr) $ List.all testPrefix [0 .. List.length pat - 1] -- Test that the prefix given is the maximal prefix. That is, -- add one more character makes it either equal to the string -- or not a prefix. prop_testCorrectPrefix :: [PatternChar] -> Property prop_testCorrectPrefix pat = let patStr = patternsToString pat lookup = computeLookup patStr isNeverSuffix len = let origPrefix = prefix len patStr -- Drop 1 to remove empty list allPrefixes = List.drop 1 $ B.inits origPrefix in List.all (\p -> B.null p || p == origPrefix || not ((B.reverse p) `B.isPrefixOf` (B.reverse origPrefix))) allPrefixes prefix len = B.take (fromIntegral len) -- True if the prefix returned from lookup for the length given produces -- a string which is a suffix of the original prefix. isRealSuffix len = (B.reverse (prefix (lookup len) patStr)) `B.isPrefixOf` (B.reverse $ prefix len patStr) isLongestSuffix len = let prefixPlus = prefix ((lookup len) + 1) patStr inputPrefix = prefix len patStr in prefixPlus == inputPrefix || not ((B.reverse prefixPlus) `B.isPrefixOf` (B.reverse inputPrefix)) testTable len = if lookup len == 0 then isNeverSuffix len else isRealSuffix len && isLongestSuffix len in not (List.null pat) ==> List.all testTable [0 .. List.length pat - 1] -- Ver