[Haskell-cafe] Input and output of mathematical expressions
Greetings Cafe, What would you recommend as a Haskell-based means of interactively reading and writing mathematical formulae? As a toy example, what might I use to write a program which presents the user with Please simplify the expression: \pi x^2 + 3\pi x^2 (Where the TeX-style expression would be presented with a greek pi and superscript twos on the xs.) The user should then have the ability to reply with something that looks like the result of TeXing 5 \pi x^2 Whatever means the user uses to enter this expression, he should be able to preview the typeset version of his input before submitting. Any ideas? Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Input and output of mathematical expressions
On 2011 Jun 9, at 16:59, Chris Smith wrote: Ae you looking to do this in a web application, or client-side? Since one of your requirements is to display a typeset equation, that makes a bit of difference. In a web-based setting, the best way to do that is probably MathML, whereas a GUI will be a bit harder. Yes, this pretty much summarizes my (ignorant) thoughts on it so far (GUI: hard; MathML: relatively easy), which is why I suspect that running it as a local web application might be the simplest way to go. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Efficient object identity (aka symbols as data)
[ TLDR: How do you do Lisp symbols in Haskell? ] What is the Haskell approach to efficient comparison and lookup of objects by their identity? Maybe a toy example would help to explain what I mean. Imagine that I want to use Haskell to maximize happiness in a situation where a bunch of people have to be assigned to certain groups according to their preferences, and some constraints on the group sizes. Conceptually my input data might be structured as follows: data Group = Group GroupName MaxGroupSize data Person = Person Name Group Group Group The program should partition the people into groups, attempting to get everyone into their most favoured groups. Whatever algorithm I choose to use for the optimization, will have to do lots of comparisons of Groups and Persons where their *identity* is all that matters: you don't need to look inside the objects. On the other hand, sometimes we will have to look inside the objects, for example in order to answer queries such as Which group did Johnny get and how far down his list of choices did that group feature?. I should be able to run the program on data that becomes available at run time. The lisper in me is crying out for (lisp-like-)symbols which I can create from the input data at run time and on which some extra information can be hung. How would I organize something like this in Haskell? Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Efficient object identity (aka symbols as data)
On 2011 May 26, at 11:12, Brandon Allbery wrote: On Thu, May 26, 2011 at 04:45, Jacek Generowicz jacek.generow...@cern.ch wrote: What is the Haskell approach to efficient comparison and lookup of objects by their identity? ghc uses Data.Unique to generate unique internal identifiers to associate with things. At first blush it sounds like the sort of thing I'm after. Thanks. (Think gensym. Hm, except last time I did anything serious with Lisp, it was Maclisp... does gensym even still exist, or did CL do something inscrutable with it?) CL has gensym. But gensym does seem to be overkill in the case I presented. I *could*, for example, say data Person = Fred | Johnny | Sally | Belinda | Kate | Roger | Eric [... and so on for a few squillion ...] data Group = Amazing | Brilliant | Cool | Great | Funky [ ... and so on for a few dozen ...] preferences :: Map Person (Group, Group, Group) In this setup (Fred == Johnny) will be very cheap, and (lookup Fred preferences) will be less cheap but possible. I'd use gensym if I need a new symbol right about which I know nothing other than I want it to be new and unique (nobody has created it before, and nobody will in the future). In the example scenario, I know what I want the symbol is to be called, and am prepared to accept the responsibility for avoiding duplicates, but I still want to be able create it at run time. In the Haskell snippet above, the compiler protects me against duplication, but forces me to know the data at compile time. In Lisp terms, I'm looking for make-symbol and intern. Beyond that, the existence of functions such as reallyUnsafePointerEquality# makes me think it's a Hard Problem. :-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Efficient object identity (aka symbols as data)
On 2011 May 26, at 11:16, Christopher Done wrote: On 26 May 2011 10:45, Jacek Generowicz jacek.generow...@cern.ch wrote: What is the Haskell approach to efficient comparison and lookup of objects by their identity? Often you just provide your own and implement Eq. I should be able to run the program on data that becomes available at run time. Typically you define an id generator and zip anything coming from the input stream up with that generator. Makes sense. Whatever algorithm I choose to use for the optimization, will have to do lots of comparisons of Groups and Persons where their *identity* is all that matters: you don't need to look inside the objects. To achieve this abstraction the usual way is just implementing Eq: instance Eq Person where Person{personId=id1} == Person{personId=id2} = id1 == id2 Any comments on the relative efficiency of the above as compared to A == B in the context of data Foo = A | B | C | D | ... lots more ... ? (I imagine that a Sufficiently Smart Compiler could reduce (==) :: Person Person to just integer comparison.) Thank you. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Efficient object identity (aka symbols as data)
On 2011 May 26, at 11:59, Brandon Allbery wrote: On Thu, May 26, 2011 at 05:41, Jacek Generowicz jacek.generow...@cern.ch wrote: On 2011 May 26, at 11:12, Brandon Allbery wrote: (Think gensym. Hm, except last time I did anything serious with Lisp, it was Maclisp... does gensym even still exist, or did CL do something inscrutable with it?) But gensym does seem to be overkill in the case I presented. (...) In Lisp terms, I'm looking for make-symbol and intern. I think I just landed on inscrutable; Nah, it's probably just me confusing you. (gensym) used to do pretty much that, it rolled symbols starting from 'a for the first one generated in a given interpreter. It still does essentially that. (Just don't be fooled by the name a: you can't access that symbol through that name. Aaaah, maybe in Maclisp it really did intern them under that name, but that would surprise me). '(gensym)' in CL is a bit like 'object()' in Python or 'new MyEmptyClass' in C++: the key point being that if you don't bind the thing being created right now, you'll never be able to get your hands on it again. Coming back on topic: Yes, I could use gensym for my purposes (though CL provides a variety of similar yet subtly different tools, which is why gensym feels a bit weird in this context). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Efficient object identity (aka symbols as data)
On 2011 May 26, at 11:59, Jacek Generowicz wrote: (I imagine that a Sufficiently Smart Compiler could reduce (==) :: Person Person to just integer comparison.) Sorry, I meant (==) :: Person - Person - Bool in the above. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot hoogle
On 2011 May 25, at 05:53, Mark Wright wrote: On Wed, 25 May 2011 02:20:39 +0200, Jacek Generowicz jacek.generow...@cern.ch wrote: I have recenly installed lambdabot. Its response to *each* *and* *every* hoogle command is *always* A Hoogle error occurred. I'm hoping that someone on Cafe might be able to offer a more helpful diagnosis than this ... erm ... terse ... error message. Hi Jacek, Hi Mark, The lambdabot hoogle command requires hoogle to be installed locally, and to work. Ah. Thank you. I had assumed that it connected to a server. (Maybe my assumption was not entirely unfounded, given that the installation instructions for lambdabot blithely state that you just cabal install lambdabot, nowhere suggesting that you might need to *manually* install some of its dependencies.) Hence the first thing to ty is to run the hoogle command line version, something like: hoogle '[a] - a' If that doesn't work, maybe try building some hoogle databases. First I needed to 'cabal install hoogle'. Having done that, I needed to do what you suggested: hoogle data Which works swimmingly on Ubuntu, but fails on OS X, because wget seems to be hard-wired. I seem to recall that at least one of the packages that I installed over the last 2 days, automatically selected wget on Ubuntu, and curl on OS X. Any pointers to the least painful way of getting 'hoogle data' to work on OS X? Once I have the hoogle command line version working, it seems that lambdabot truncates its output to just the first 3 lines. Is this normal? Is there a way of customizing or changing this behaviour? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot check
Hi Mark, Thanks for your wonderfully lucid, concise and complete explanation of the problem and its solution (included below). When I apply your patch and reinstall lambabot, I now get the following problem: lambdabot check True Could not find module `ShowIO`: It is a member of the hidden package `show-0.3.4`. Use -v to see a list of the files searched for. I recognize the message about -v as a ghci one. How could I inject this -v into lambabot ? I get the same error on both of the machines on which I am trying this. On one of them I already have show-0.3.4 and show-0.4.1.1, on the other I have only show-0.4.1.1. Any suggestions? On 2011 May 25, at 06:06, Mark Wright wrote: Hi Jacek and Gwern, In the upgrade from mueval from 0.8 to 0.8.1, some of the mueval command line options were changed: --loadfile = --load-file --noimports = --no-imports For Plugins/Check.hs I change --loadfile to -l. To convince lambdabot to run on gentoo, I patch it to use --no- imports to avoid this problem: % mueval -e '1 + 2' Ambiguous module name `Control.Monad.Cont': it was found in multiple packages: monads-fd-0.1.0.2 mtl-2.0.1.0 monads-tf-0.1.0.0 % And I patch the lambdabot /usr/share/lambdabot-4.2.3.2/ghc-7.0.3/ State/L.hs to used -XPackageImports. Then mueval works: % mueval --no-imports -l ~/.lambdabot/State/L.hs -e '1 + 2' 3 % And lambdabot works: % lambdabot Initialising plugins ... done. lambdabot @check True +++ OK, passed 100 tests. OK, passed 100 tests. lambdabot The patch is here: https://github.com/markwright/gentoo-haskell/blob/master/dev-haskell/lambdabot/files/lambdabot-4.2.3.2-eval.patch Regards, Mark ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot hoogle
On 2011 May 25, at 13:10, Mark Wright wrote: I assume your test on OS X was with the latest hoogle version so that old issues would no longer be relevant: I would be surprised if it weren't the latest, as I started installing everything from scratch a couple of days ago. Anyway, my hoogle version is 4.2.3, which is the most recent, AFAICT (ie, it's the highest version number on hackage) but I have tripped over so many things on this trip, that I wouldn't be surprised by anything any more. Once I have the hoogle command line version working, it seems that lambdabot truncates its output to just the first 3 lines. Is this normal? Yes. Is there a way of customizing or changing this behaviour? No (other than patching lambdabot), so the obvious workaround is to run the hoogle from the command line. Understood. Thank you. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot hoogle
On 2011 May 25, at 16:41, Gwern Branwen wrote: On Wed, May 25, 2011 at 6:22 AM, Jacek Generowicz jacek.generow...@cern.ch wrote: I had assumed that it connected to a server. It did at one point, but Hoogle had downtime and the local hoogle command was just as good and worked offline. Makes sense. (Maybe my assumption was not entirely unfounded, given that the installation instructions for lambdabot blithely state that you just cabal install lambdabot, nowhere suggesting that you might need to *manually* install some of its dependencies.) Well, does every lambdabot user want mueval and hoogle installed? Quite possibly not, but it would it be too much to ask, to have the documentation mention that they need to be installed separately if you intend to use them through lambdabot? I've already stumbled across mueval and hoogle as things that need to be installed separately before the full advertized features of lambdabot work. With this experience under my belt and the benefit of hindsight, I vaguely, almost, kinda, maybe see how I could have guessed that the stubborn response A Hoogle error occurred. to any hoogle command in lambdabot, means that I need to install hoogle locally: 'hoogle ...' -- A Hoogle error occurred. == install hoogle. But how on earth was I supposed to guess that in order to make 'check' work, the package to install was 'mueval', given that the error message was Terminated? 'check ...' -- Terminated == install mueval. Hmmm. What other lambdabot features rely on packages that need to be installed separately? Once I have the hoogle command line version working, it seems that lambdabot truncates its output to just the first 3 lines. Is this normal? Is there a way of customizing or changing this behaviour? It's normal, yeah. Don't want to spam #haskell with 100 lines of useless matches. Agreed. I guessed that this would be the motivation. Configurable? Not really. OK. Thank you. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot hoogle
On 2011 May 25, at 21:04, Neil Mitchell wrote: Hi Jacek, Hi Neil, Any pointers to the least painful way of getting 'hoogle data' to work on OS X? Set up a shell alias so wget just calls curl? Their interfaces are different. (Though maybe there's some option which makes curl sufficiently similar to wget, but I haven't bothered to look because ...) Install wget on OS X? Yes. Download, untar, configure, make, sudo make install ... did the trick in about two minutes. (Kinda obvious really, wasn't it! I plead mitigating circumstances because my brain has been beaten to a pulp by all the stumbling through installations I have been doing over the last 3 days.) Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot hoogle
On 2011 May 25, at 17:42, Gwern Branwen wrote: On Wed, May 25, 2011 at 11:08 AM, Jacek Generowicz jacek.generow...@cern.ch wrote: I've already stumbled across mueval and hoogle as things that need to be installed separately before the full advertized features of lambdabot work. With this experience under my belt and the benefit of hindsight, I vaguely, almost, kinda, maybe see how I could have guessed that the stubborn response A Hoogle error occurred. to any hoogle command in lambdabot, means that I need to install hoogle locally: 'hoogle ...' -- A Hoogle error occurred. == install hoogle. But how on earth was I supposed to guess that in order to make 'check' work, the package to install was 'mueval', given that the error message was Terminated? 'check ...' -- Terminated == install mueval. You weren't really meant to - lambdabot isn't exactly meant for anyone who won't look at the source when something goes wrong. Understood. Fair enough. I feel a bit guilty about spamming the list with all my stupid problems: I would prefer to find my own way around, but if I had to dive in and rummage around the source for every problem that I encounter, I would not get very far. What other lambdabot features rely on packages that need to be installed separately? Brainfuck and unlambda are separate executables, but they already have deps. I must admit that hoogle and check were far stronger incentives to try to intstall lambdabot, than brainfuck and unlambda :-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot check
On 2011 May 25, at 16:09, Mark Wright wrote: Hi Jacek, Hi Mark, Thanks once again for your excellent answer. The show module names were changed in the upgrade from show 0.3.4 to show 0.4.1.1. OK, I see that in show.cabal, ShowIO disappears from the exposed- modules section. This is confirmed by the fact that Show.hs has disappeared from the source. The contents of the latter were just a single instance declaration which now appears in ShowFun.hs. From all this I infer that lambdabot uses show, and in the process wants to import ShowIO: Such imports are indeed found in State/L.hs and State/Pristine.hs. Given that everything that used to live in ShowIO has been swallowed by ShowFun, we could just import ShowFun at those to place instead. On gentoo I conditionally sed lambdabot to account for this, then print out a note that the user may need to copy the State/* files, in particular L.hs and Pristine.hs for this problem, With you so far .. to ~/.lambdabot/State. Huh? is ~/.packagename/ some sort of cabal convention? Or are you using it as a shorthand for ~/.cabal/packages/yaddayadda/packagename ? Or is it some way in which you *could* organize your Cabal packages which happens to be different from what I have on my systems (by default)? Ah, it is nothing to do with cabal, it's just lambdabot's personal data! (Which needs to have State/L.hs in it. It seems to work without Pristine.hs. Fine, at this stage I'm just prepared to accept this directory as magic). I seem to have a working lambabot check. (i.e. 'lambdabot check True' claims to pass 100 tests.) Thank you. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot hoogle
On 2011 May 25, at 23:20, Brandon Moore wrote: From: Jacek Generowicz Sent: May 25, 2011 2:45 PM I feel a bit guilty about spamming the list with all my stupid problems: I would prefer to find my own way around, but if I had to dive in and rummage around the source for every problem that I encounter, I would not get very far. I'm not particularly interested in lambdabot myself, but this seems like a reasonable conversation for this list, and the sort of thing that's nice to have recorded in the mailing list archives - and hopefully folded back into appropriate package descriptions and wiki pages. I'm hoping to find some time at the end of this journey to gather together what I have learned on the way, and to try to feed some of the information back into relevant places. (Any pointers on how to do this most productively would be welcome.) But my fear is that by the time I am done, I will have used up all my Haskell time for this quarter. I wonder a few quick greps for error messages in the source code might have turned up something useful without too much trouble, I wonder myself too. From my point of complete ignorance about how the packages are put together, and almost complete ignorance about cabal, it's difficult to judge when (and for how long) it's worth digging in with grep etc.: sometimes it will be a fruitful exercise, and sometimes not. Sometimes someone else will understand my problem faster than I can type grep, and sometimes not. So my tactic is to dig a little, then send out a cry for help, before digging further. but from skimming messages it seems your efforts have been at least as much as can reasonably be expected for installing a cabal package without big giant disclaimers. Thank you for your kind words. I hope that most others find my spam as inoffensive as you do. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
On 2011 May 23, at 16:02, Johannes Waldmann wrote: I just did this (in a pristine virtual machine): * install ubuntu-11.04-desktop-amd64.iso * sudo apt-get install libgmp3-dev zlib1g-dev libglut3-dev * install from binary ghc-7.0.3-x86_64-unknown-linux.tar.bz2 * install from source haskell-platform-2011.2.0.1.tar.gz and this definitely works, i.e. 'ghc-pkg list' shows the platform modules, and no errors. If you haven't trashed that VM yet, would you mind checking whether lambdabot cabal-installs cleanly? (Modulo giving it things that it might need such as a readline-dev package.) Thanks ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Cabal: top level dependency base -any
Hi, Could anyone shed light on the meaning of this error message? cabal: cannot configure xmonad-0.9.1 It requires base ==3.* For the dependency on base ==3.* there are these packages: base-3.0.3.1 and base-3.0.3.2. However none of them are available. base-3.0.3.1 was excluded because of the top level dependency base -any base-3.0.3.2 was excluded because of the top level dependency base -any My guess is that -any would mean either that any version is acceptable (in which case should always work, including this time) or that -any means that any version is unacceptable, in which case it would never work, which is daft. So clearly I don't understand what it is trying to say. Any hints? Is this documented anywhere? Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal: top level dependency base -any
On 2011 May 24, at 09:28, Andres Loeh wrote: Hi. Could anyone shed light on the meaning of this error message? cabal: cannot configure xmonad-0.9.1 It requires base ==3.* For the dependency on base ==3.* there are these packages: base-3.0.3.1 and base-3.0.3.2. However none of them are available. base-3.0.3.1 was excluded because of the top level dependency base - any base-3.0.3.2 was excluded because of the top level dependency base - any It's not a great error message. Yes, xmonad-0.9.1 requires base ==3.*. So far, so good. Now, base is a special package. It comes with ghc, and cannot be upgraded. That's why Cabal will rule out all base versions but the one you already have installed. If you have a recent ghc, that'll be base-4. So Cabal is correct to fail in this case: you cannot install this version of xmonad with this version of ghc. That makes sense. Thanks your the explanation. So would it be correct to infer that the -any restriction will only (and always) come into play with special packages such as base? Are there any other special packages besides base? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal: top level dependency base -any
On 2011 May 24, at 09:28, Ivan Lazar Miljenovic wrote: On 24 May 2011 16:57, Jacek Generowicz jacek.generow...@cern.ch wrote: Hi, Could anyone shed light on the meaning of this error message? cabal: cannot configure xmonad-0.9.1 It requires base ==3.* For the dependency on base ==3.* there are these packages: base-3.0.3.1 and base-3.0.3.2. However none of them are available. base-3.0.3.1 was excluded because of the top level dependency base - any base-3.0.3.2 was excluded because of the top level dependency base - any [...] Any hints? Yes: use xmonad-0.9,2 instead! It supports base-4, which is probably what you have (with GHC-7.0.*). Indeed, I discovered that to be the solution in the meantime, as I noticed that on my other system xmonad-0.9.2 was being installed by cabal install. Doing a cabal update made everything go through (with xmonad-0.9.2). Which makes me wonder why the two systems had different ideas of what the most recent xmonad version was, as I installed both of them yesterday afternoon. I seem to be discovering a rule of thumb: do a cabal update *every time* you want to cabal install. Anyway, thanks for the hint. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] *GROUP HUG*
On 2011 May 24, at 09:37, Juan Daugherty wrote: Every computing culture is different. Being in the habit of asking questions you should be able to answer yourself is not a good idea. Why did you ask a question which you yourself characterize as ignorant? I would guess it is because he was attempting to reduce his ignorance. That, to me, is one of the more noble reasons for asking questions. What would be the point of asking a non-ignorant question, unless it is a rhetorical one? It is tempting to infer from what you wrote above, that you believe all ignorant questions are ones which you should be able to answer yourself. I respectfully disagree. Then there is the whole class of questions which you could answer yourself, but the effort required to do so can be reduced by many orders of magnitude with some external input. Another good reason to ask questions. If you ask questions, and then stubbornly ignore good advice that people give you, then you shouldn't be surprised if they turn hostile. But if they are hostile merely because you asked an ignorant question, then I do find that surprising. Signed, an ignoramus who is constantly trying to chip away at his own ignorance (and that of others). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] GOA broken with recent lambdabots
GOA is broken with recent lambdabots, according to http://hackage.haskell.org/package/goa-3.0.2 It certainly fails to compile for me (like this http://hpaste.org/46994/goa_build_failure ) From the fact that it is known to be broken, should I infer that it is a difficult problem that would take an expert a long time to fix? Or is it broken merely because nobody has got around to fixing it, and would somebody (like me) who is not a Haskell expert and has never looked into the source of lambdabot or GOA, stand a chance of fixing it? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GOA broken with recent lambdabots
On 2011 May 24, at 10:13, Christopher Done wrote: On 24 May 2011 10:05, Jacek Generowicz jacek.generow...@cern.ch wrote: GOA is broken with recent lambdabots, according to http://hackage.haskell.org/package/goa-3.0.2 It certainly fails to compile for me (like this http://hpaste.org/46994/goa_build_failure ) I can fix it tonight. Not a big deal. Great. Thanks. Curious; do people still use GOA? It sounds like a very useful tool, but as I have never managed to install it yet, I don't know what it will be like in reality. I do imagine myself using it though. I run GHCi within my Emacs, which allows me to interactively test ideas while I'm writing programs, and GOA promises to put so many more useful tools at my fingertips built in to the same environment. It looks *very* useful. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Cabal: disabling -fvia-C
I hope you will pardon another *ignorant* question. 'cabal install lambdabot' fails on Ubuntu Natty. According to the following exchange and bug report http://comments.gmane.org/gmane.comp.lang.haskell.cafe/88735 http://hackage.haskell.org/trac/ghc/ticket/5050 the workaround is not to use -fvia-C. I have found an {-# OPTION -fvia-C #-} deep inside the lambdabot code in Plugin/Pl/Common.hs. How can I tell cabal install to ignore this? Is there some command line option for doing so, or do I have to edit the source code and somehow persuade cabal to use my hacked version ? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal: disabling -fvia-C
On 2011 May 24, at 11:12, Jacek Generowicz wrote: I have found an {-# OPTION -fvia-C #-} deep inside the lambdabot code in Plugin/Pl/Common.hs. How can I tell cabal install to ignore this? Is there some command line option for doing so, or do I have to edit the source code and somehow persuade cabal to use my hacked version ? The edited source code is ignored by cabal install. However, if you tar.gz the edited source code and replace the original tarball (making sure that you do *not* remove the untarred directory (it seems that you can remove its contents, but not the directory itself)), then cabal install works and lambdabot installs. But I can't help feeling that this is not the smartest way to solve this problem. It looks like a random solution achieved by someone who doesn't understand what is going on. Is there a more sensible way to do this? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal: disabling -fvia-C
On 2011 May 24, at 11:49, Henning Thielemann wrote: You cannot only run $ cabal install lambdabot but you can also switch to lambdabot source directory and call lambdabot$ cabal install Ah. That's useful. I tried manually going through the Cabal song and dance in that directory, but it failed to find the dependencies, which presumably will be managed by your suggestion. Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] lambdabot check
I've installed lambdabot, but check within it seems to be broken: the only answer it ever gives is Terminated. For example: lambdabot check True Terminated lambdabot quickCheck works just fine in a GHCi session: Prelude :m + Test.QuickCheck [...] Prelude quickCheck True [...] +++ OK, passed 100 tests. (GHC 7.0.3 on Ubuntu Natty, everything freshly installed with cabal install as far as possible.) Any advice? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] lambdabot check
On 2011 May 24, at 22:30, Gwern Branwen wrote: @check these days goes through mueval. Are you sure mueval is installed working? Au contraire: I am sure that mueval was *not* installed. (Am I justified to be a just a little bit annoyed that it was not installed as a dependency by cabal install? Or that there was no indication whatsoever that mueval's absence was the cause of the problem?) Now that I have installed it explicitly myself, I do seem to make some more progress, but it's still far short of the ideal: lambdabot check True unrecognized option `--loadfile=' Usage: mueval [OPTION...] --expression EXPRESSION... -p PASSWORD--password=PASSWORD The password for the mubot account. If this is set, mueval will attempt to setuid to the mubot user. This is optional, as it requires the mubot user to be set up properly. (Currently a null-op.) [etc. etc.] You can try running the tests.sh script which will exercise the QuickCheck functionality among other things. This, AFAICT, seems to go just fine. There's lots of output with which I won't spam you, other than to say that it includes the text OK, all the valid expressions worked out well. Now let's test various misbehaved expressions. The last line of the output is IO . So, it seems that I am now faced with the problem of getting lambdabot and mueval to talk to each other sensibly. Any pointers would be gratefully received. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] lambdabot hoogle
I have recenly installed lambdabot. Its response to *each* *and* *every* hoogle command is *always* A Hoogle error occurred. I'm hoping that someone on Cafe might be able to offer a more helpful diagnosis than this ... erm ... terse ... error message. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
[TL;DR: there's a concrete question at the bottom.] Once again I find myself in the pleasant situation where the slings and arrows of life in general are slightly less intense, and I manage to find a few spare minutes and some free brain cycles to dedicate to Haskell. Why not try GHC 7.0.3? (after all, GHC 7 has been out for a good few months, so the teething troubles should have passed by now), and there's a lovely new Haskell Platform 2011.2.0.1 to go with it, so, maybe this time, I'll actually be able to use some of the libraries that I tried and failed to install during my last period of Haskell study. The two computers I have available for playing with Haskell run OS X Leopard (10.5), and Ubuntu Natty (11.04). First up OS X: It seems that GHC 7 (and consequently Platform 2011.2) require OS X 10.6. OK, let's forget that one. Next up: Ubuntu. There's a Linux Link on the Haskell Platform Page. Ooooh, there's an Ubuntu link. Ooooh! there's even a package for Natty, great! Version 2010.1.0.0.1 WTF? Where's the 2011.2 package? There isn't one. OOoooK. Any workarounds. Well, we can install from source, apparently. But we need GHC 7.0.3 first. Fine. Done. Now let's install the platorm. [Does obvious thing, compilation fails.] Hmm, let's follow the Complete instructions for installing from source http://www.vex.net/~trebla/haskell/haskell-platform.xhtml just in case I did something stupid. [Follows instructions: failure.] OK, maybe something somewhere is causing some confusion with previously installed versions of GHC, Cabal, whatever. [Performs Haskell pogrom on system: removes all traces of anything Haskell related. Follows Complete instructions [...] WORD ... FOR ... WORD. Failure]. Aaaargh ! I can't take it any more. I just want to write some Haskell, and every time I want to venture beyond the safe confines of the Prelude I get bogged down in installation hell. Next time I have some spare time, I will be more reluctant to risk having that time stolen by the Haskell infrastructure installation process. So, after this tale of agony, here are two concrete questions: a) Am I right in concluding that GHC 7.0.3 will not run on OS X 10.5 (without unreasonable effort)? b) On Ubuntu Natty I installed the generic linux GHC 7.0.3 binary. Downloaded Haskell Platform 2011.2.0.1 source distribution. ./ configure worked happily. make fails as follows. Building transformers-0.2.2.0 /usr/local/haskell-platform-2011.2.0.1/bin/ghc --make Setup -o Setup -package Cabal-1.10.1.0 command line: cannot satisfy -package Cabal-1.10.1.0: Cabal-1.10.1.0-1fb2094e19492373b1a39284193e7984 is unusable due to missing or recursive dependencies: process-1.0.1.5-55dfaccf3a91c4cb8f6284a0bafef198 Could anybody help me get past this problem? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
On 2011 May 23, at 13:45, Anthony Cowley wrote: On Mon, May 23, 2011 at 5:17 AM, Jacek Generowicz jacek.generow...@cern.ch wrote: a) Am I right in concluding that GHC 7.0.3 will not run on OS X 10.5 (without unreasonable effort)? This is a frustrating situation. Note that there is a binary for 7.0.1 that supports 10.5 http://www.haskell.org/ghc/download_ghc_7_0_1#macosxintel. OK, that was painless. Thanks! From this, you should be able to build 7.0.3 yourself. That's interesting. I won't try that *right* now. As for the platform, if it is giving you trouble, don't shy away from just using GHC and cabal as normal! After you've cabal installed a few big packages, you will find that you've acquired many of the most popular packages. If by cabal install you mean use the command cabal ... yeah, that would be great, if only I could install cabal-install, which fails. Or do you mean manual install of Cabal packages? Either way, I'm not making much progress. b) On Ubuntu Natty I installed the generic linux GHC 7.0.3 binary. Downloaded Haskell Platform 2011.2.0.1 source distribution. ./ configure worked happily. make fails as follows. Building transformers-0.2.2.0 /usr/local/haskell-platform-2011.2.0.1/bin/ghc --make Setup - o Setup -package Cabal-1.10.1.0 command line: cannot satisfy -package Cabal-1.10.1.0: Cabal-1.10.1.0-1fb2094e19492373b1a39284193e7984 is unusable due to missing or recursive dependencies: process-1.0.1.5-55dfaccf3a91c4cb8f6284a0bafef198 The Ubuntu HP story is a bit of a gotcha for the innocent user, too. But, again, you can happily install GHC 7.0.3, and then cabal install your way to happiness. Maybe if I managed to install just one package manually, then I might start sharing some of you optimism :-) The problem you encountered seems due to a conflict among packages that came with GHC. Which does seem rather odd, doesn't it? I'm tempted to think that I didn't quite manage to nuke everything, because I find it hard to believe that GHC itself comes with internal conflicts which The Google seems not to have heard about. I think your strategy of nuking everything Haskell through your package manager (if available), then manually (not forgetting ~/.ghc and ~/.cabal) was prudent to get out of the hole you found yourself in. Yup, ~/.ghc and ~/.cabal didn't escape my attention. Except that it doesn't seem to have worked (yet - hope springs eternal). When I ghc-pkg check, I get lots of complaints about ~/.cabal/lib/ somelibrary/ghc-7.0.3 not being found. Erm, I nuked it all and then installed ghc-7.0.3 from scratch (generic Linux binary package), so I've no idea *why* my system thinks that these should exist unless *it* put them there after the purge during the installation of ghc. Any ideas how to solve this? But don't let HP installation troubles keep you away from Haskell altogether! I'm determined not to let that happen, but when the few precious moments I can afford to spend on Haskell end up being spent on installation troubles rather than Haskell itself, then it does become rather tough to keep the motivation. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
On 2011 May 23, at 14:29, Anthony Cowley wrote: On Mon, May 23, 2011 at 8:16 AM, Jacek Generowicz jacek.generow...@cern.ch wrote: On 2011 May 23, at 13:45, Anthony Cowley wrote: As for the platform, if it is giving you trouble, don't shy away from just using GHC and cabal as normal! After you've cabal installed a few big packages, you will find that you've acquired many of the most popular packages. If by cabal install you mean use the command cabal ... yeah, that would be great, if only I could install cabal-install, which fails. Or do you mean manual install of Cabal packages? Either way, I'm not making much progress. What I do is get GHC installed, then download the cabal-install package from hackage and use the bootstrap.sh installer it comes with. Then you can use the cabal executable to install packages as you go. Been there, done that, got the crashes :-( I've had the pleasure of watching the bootstrap.sh crash a number of times now. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
On 2011 May 23, at 14:16, Jacek Generowicz wrote: On 2011 May 23, at 13:45, Anthony Cowley wrote: On Mon, May 23, 2011 at 5:17 AM, Jacek Generowicz jacek.generow...@cern.ch wrote: I think your strategy of nuking everything Haskell through your package manager (if available), then manually (not forgetting ~/.ghc and ~/.cabal) was prudent to get out of the hole you found yourself in. Yup, ~/.ghc and ~/.cabal didn't escape my attention. Hmm, maybe I was mistaken, and maybe ~/.ghc survived. I nuked everything again (there was a .ghc: I assumed it had been re-created, but maybe it was an old one (I didn't check the datestamps), but no .cabal). Now 'make' and 'make install' *have* worked for HP. Haven't got around to trying to use it yet, but I thought I'd share the good news. Thanks for your moral support, it seems to have done the trick :-) Conclusion: I *probably* failed to remove ~/.ghc, so some old data were interfering with the supposedly clean installation. A manual install of the GHC 7.0.3 generic Linux binary, followed by installation from source of HP 2011.2.0.1 *has* worked for me on Ubuntu Natty, once I nuked *all* previous traces of Haksell on the system. I *did* have to install libgmp in order for the configuration step of HP to succeed. Thanks for your help. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
On 2011 May 23, at 14:42, Daniel Fischer wrote: On Monday 23 May 2011 14:16:43, Jacek Generowicz wrote: If by cabal install you mean use the command cabal ... yeah, that would be great, if only I could install cabal-install, which fails. With what error? Downloading and unpacking the .tar.gz bundle and then running $ ./bootstrap.sh in that directory should work. Below is what I get *now* having just successfully installed a fresh GHC 7.0.3 and HP 2011.2.0.1. By successfully installed I mean that configure, make and make install didn't throw up any errors. I haven't tested that anything works yet. $ ./bootstrap.sh Checking installed packages for ghc-7.0.3... parsec-2.1.0.1 will be downloaded and installed. network is already installed and the version is ok. Cabal-1.8.0.2 will be downloaded and installed. mtl-1.1.0.2 will be downloaded and installed. HTTP-4000.0.8 will be downloaded and installed. zlib is already installed and the version is ok. Downloading parsec-2.1.0.1... ... Downloading Cabal-1.8.0.2... ... [56 of 58] Compiling Distribution.Simple.UserHooks ( Distribution/ Simple/UserHooks.hs, Distribution/Simple/UserHooks.o ) [57 of 58] Compiling Distribution.Simple ( Distribution/Simple.hs, Distribution/Simple.o ) [58 of 58] Compiling Main ( Setup.hs, Setup.o ) Linking Setup ... Configuring Cabal-1.8.0.2... Setup: At least the following dependencies are missing: base =4 3 =1 5, filepath =1 1.2 Error during cabal-install bootstrap: Configuring the Cabal package failed Or do you mean manual install of Cabal packages? That's not very comfortable, since you have to chase dependencies manually. Spending some effort to get cabal-install installed is definitely worth it. My thoughts exactly. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
On 2011 May 23, at 15:08, Jacek Generowicz wrote: On 2011 May 23, at 14:42, Daniel Fischer wrote: $ ./bootstrap.sh in that directory should work. Configuring Cabal-1.8.0.2... Setup: At least the following dependencies are missing: base =4 3 =1 5, filepath =1 1.2 How am I supposed to interpret the constraint on base? I read that as it has to be not less than 4 but less than 3 In other words, it requires an *impossible* version of base ! 'ghc-pkg list' claims that I have base 4.3.1.0 filepath 1.2.0.0 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
On 2011 May 23, at 15:22, Daniel Fischer wrote: On Monday 23 May 2011 15:08:41, Jacek Generowicz wrote: Cabal-1.8.0.2 will be downloaded and installed. That's a bad sign. Have you downoaded the bundle from the cabal-install page? Ermmm, ys [sudden pangs of guilt] was that not the right thing to do? That's not the right thing to do Darn! (yeah, somebody should tell unsuspecting travellers). We would kinda appreciate it :-) With ghc-7, you should use cabal-install-0.10.*, download cabal- install-0.10.2 from hackage http://hackage.haskell.org/package/cabal-install Done ... base =4 3 =1 5, filepath =1 1.2 You see that that constraint is impossible, don't you? Yes, but I suspected my inability to read the constraint properly. Okay, $ghc-pkg unregister parsec-2.1.0.1 (unless you want to keep it) Try it with cabal-install-0.10.2, Bingo! sorry for the inconvenience. Marvin I think ... I feel good about it. /Marvin Many, many thanks for your help. (GHC 7.03 is compiling away on OS X, BTW, no glitches so far). ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] GHC 7, Platform 2011.2 vs OS X 10.5, Ubuntu 11.04
Summarizing, by answering my own question on the basis of the help I have received elsewhere in the thread. On 2011 May 23, at 11:17, Jacek Generowicz wrote: a) Am I right in concluding that GHC 7.0.3 will not run on OS X 10.5 (without unreasonable effort)? It takes little effort on the part of the human, though the CPU will have to work hard. - Make sure you have XCode 3.1 (or better, I guess) - Download and install GHC-7.0.1 http://www.haskell.org/ghc/download_ghc_7_0_1#macosxintel - Use the above to compile GHC-7.0.3 from source. b) On Ubuntu Natty I installed the generic linux GHC 7.0.3 binary. Downloaded Haskell Platform 2011.2.0.1 source distribution. ./ configure worked happily. make fails as follows. Building transformers-0.2.2.0 /usr/local/haskell-platform-2011.2.0.1/bin/ghc --make Setup - o Setup -package Cabal-1.10.1.0 command line: cannot satisfy -package Cabal-1.10.1.0: Cabal-1.10.1.0-1fb2094e19492373b1a39284193e7984 is unusable due to missing or recursive dependencies: process-1.0.1.5-55dfaccf3a91c4cb8f6284a0bafef198 Could anybody help me get past this problem? This problem was probably caused by having an old ~/.ghc lying around. On a *clean* Natty system, this procedure works like a charm, though you may have to apt-get install some required C libraries. If you then proceed to install cabal-install, make sure *not* to use the version which is available for download (today) on the cabal- install page: for GHC 7 you need to use cabal-install version 0.10.*, which you can get from http://hackage.haskell.org/package/cabal-install Use the booststrap.sh script which comes in the bundle (chmod u+x bootstrap.sh; ./bootstrap.sh). Thanks to all those who helped. Hopefully this summary will be of some use to someone in the future. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Further installation adventures
I'm trying to cabal install lambdabot. This depends on a squillion other libraries, which cabal tries to install, among which is readline, which fails to configure as follows. Configuring readline-1.0.1.0... checking for gcc... gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no checking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking for GNUreadline.framework... checking for readline... no checking for tputs in -lncurses... no checking for tputs in -ltermcap... no checking for tputs in -lcurses... no checking for rl_readline_version... no configure: error: readline not found, so this package cannot be built See `config.log' for more details. cabal: Error: some packages failed to install: readline-1.0.1.0 failed during the configure step. The exception was: ExitFailure 1 From which I conclude that it can't find the readline library. I have all sorts of flavours of readline on my system, so I'll need a bit more information about what exactly it's looking for. It tells me to look in config.log. I presume that this is the config log of the cabal package readline, which cabal automatically downloaded, unpacked ... and presumably automatically cleaned up at the end, because I can't find it anywhere. Where should I be looking for the relevant config.log? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Further installation adventures
On 2011 May 23, at 19:31, Marc Weber wrote: Excerpts from Jacek Generowicz's message of Mon May 23 19:15:53 +0200 2011: Where should I be looking for the relevant config.log? Maybe you're missing header files? I checked whether the -dev packages were installed, and they were present ... but your message prompted me to check again, and it turns out that I had deluded myself. So, yes, absence of headers turned out to be the problem. Thanks. Onward. Readline has installed, But now 'cabal install lambdabot' fails almost exactly like this: http://hpaste.org/46397/lambdabot_install_failure (Note, that paste isn't mine, it popped up in a Google search.) Any suggestions, anyone? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] groupBy huh?
Hi Cafe, It seems that I don't understand what groupBy does. I expect it to group together elements as long as adjacent ones satisfy the predicate, so I would expect ALL four of the following to give one group of 3 and a group of 1. Prelude :m + Data.List Prelude Data.List groupBy () abcb [abcb] Prelude Data.List groupBy () abca [abc,a] Prelude Data.List groupBy () [1,2,3,2] [[1,2,3,2]] Prelude Data.List groupBy () [1,2,3,1] [[1,2,3],[1]] What am I missing? Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] groupBy huh?
On 2011 Mar 4, at 01:39, Marc Weber wrote: Excerpts from Jacek Generowicz's message of Fri Mar 04 00:18:07 + 2011: Prelude Data.List groupBy () [1,2,3,2] [[1,2,3,2]] This is wired. However if you think about the algorithm always using the first element of a list and comparing it against the next elements you get 1 2 ok, same group 1 3 dito 1 2 dito Thus you get [[1,2,3,2]] OK, that works, but it seems like a strange choice ... On 2011 Mar 4, at 01:47, Daniel Fischer wrote: On Friday 04 March 2011 01:18:07, Jacek Generowicz wrote: What am I missing? That groupBy expects an equivalence relation ... Bingo! Now it makes sense. (iirc, that was documented some time, seems to be gone, there's only a hint left at the docs for group equality test). Hmph. In my opinion, explicitly including the words equivalence relation would immensely improve the documentation. Thank you for you clarifications, gentlemen. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] groupBy huh?
On 2011 Mar 4, at 02:14, Brandon S Allbery KF8NH wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 3/3/11 20:09 , Jacek Generowicz wrote: 1 2 ok, same group 1 3 dito 1 2 dito Thus you get [[1,2,3,2]] OK, that works, but it seems like a strange choice ... Stability is often valued in functions like this: the order of elements is not altered. I'm failing to see how the behaviour I expected would change the order of elements: the elements would still come out in exactly the same order, it is just the boundaries between the groups would be in different places. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] IO, sequence, lazyness, takeWhile
On 2010 Dec 19, at 20:10, Brandon S Allbery KF8NH wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 12/13/10 09:15 , Jacek Generowicz wrote: untilQuit' = (fmap (takeWhile (/= quit))) (sequence $ map (= report) (repeat getLine)) -- The latter version shows the report, but it doesn't stop at the -- appropriate place, so I'm guessing that I'm being bitten by my -- ignorance about the interaction of actions and lazyness. The reason this doesn't stop where you expect it to is that sequence is effectively strict That would explain it. Thank you. Where is this fact documented? I mostly rely on Hoogle, which gets me to http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v :sequence which says nothing about strictness. How could I have known this without having to bother anyone else? You want the stop condition between the map-report and the repeat- getLine. Or, more generally speaking, between sequence, and whatever generates the infinite list. But can this be done in a similar style? Could I still use takeWhile and somehow lift it into IO? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] (Read r) = IO (Maybe r)
Hi, What are some interesting, idiomatic ways of writing something similar to the following, using a) Only standard utilities b) Non-standard utilities getValidatedInteger = do maybeInt - maybeGet case maybeInt of Just int - return int Nothing - do putStrLn That doesn't seem to be an integer. Try again. getValidatedInteger maybeGet :: (Read r) = IO (Maybe r) maybeGet = getLine = return . maybeReadS maybeReadS text = case reads text of [(int, rest)] | all (== ' ') rest - Just int _ - Nothing ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Making type-incompatible strategies interchangeable
# Imagine an activity which may be performed either by a computer, or # by a human (alternatively, either locally, or remotely across a # network). From Haskell's type system's perspective, these two will # look completely different (most obviously, the human (or the # network) is wrapped in IO). How can they be made interchangeable ? # To demonstrate what I mean, I offer the following concrete toy # example, in Python. # It's a harness for playing the trivial higher-lower number guessing # game, with interchangeable strategies for either player. In this # example I provide two strategies (Computer / ask Human via IO) for # each role (asker and guesser). # How can this sort of interchangeability of computations which are # conceptually identical, but incompatible from the types perspective, # be expressed in Haskell? from random import randint # A simple game harness. It is given the two players, and mediates the # interaction between them. def game(asker, guesser): feedback = None count = 0 while not feedback == 0: guess = guesser(feedback) feedback = asker(guess) print Guess: %s, Answer: %s % (guess, feedback) count += 1 print Got it in, count # A couple of decorators to smoothe the use of the generators which # are used to implement the players. def hide_send(generator_function): def proxy(*args, **kwds): return generator_function(*args, **kwds).send return proxy def advance(hidden_send_proxy): def proxy(*args, **kwds): send = hidden_send_proxy(*args, **kwds) send(None) return send return proxy # Artificial player who knows the secret @advance @hide_send def higher_lower_asker_C(low=0, high=100): secret = randint(low, high) guess = yield while True: guess = yield cmp(guess, secret) # Artificial player trying to guess the secret @hide_send def higher_lower_guesser_C(low=0, high=100): while True: guess = (low + high) // 2 feedback = yield guess if feedback 0: low = guess else: high = guess # Interface to human who knows the secret @advance @hide_send def higher_lower_asker_H(): guess = yield # No feedback before first guess while True: print My guess is, guess print Please reply with one letter: is my guess (l)ow, (c)orrect or (h)igh ? guess = yield {'l':-1, 'c':0, 'h':1 }[raw_input()] # Interface to human trying to guess @hide_send def higher_lower_guesser_H(): while True: feedback = yield input(What is your guess? ) print {-1:Too low., 0:Correct!, +1:Too high.}[feedback] # Given the above preparation, the game can now be played in all 4 # possible permutations of Computer/Human vs. Computer/Human. game(higher_lower_asker_C(), higher_lower_guesser_C()) game(higher_lower_asker_H(), higher_lower_guesser_C()) game(higher_lower_asker_C(), higher_lower_guesser_H()) game(higher_lower_asker_H(), higher_lower_guesser_H()) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] IO, sequence, lazyness, takeWhile
-- Is it possible to rewrite code written in this style untilQuit = do text - getLine report text if text == quit then return () else untilQuit -- in a style using higher order functions for abstract iteration? For -- example, something along these lines: untilQuit' = (fmap (takeWhile (/= quit))) (sequence $ map (= report) (repeat getLine)) -- The latter version shows the report, but it doesn't stop at the -- appropriate place, so I'm guessing that I'm being bitten by my -- ignorance about the interaction of actions and lazyness. -- For completeness, here's a definition of report report text = do putStrLn $ You wrote ++ text return text ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Cabal, xmonad-contrib, X11-xft, pkg-config ... questioning my sanity
In short: I can't cabal install xmonad-contrib. Longer version: It a appears that a program which does not exist on my computer seems to insist on a package version which does not exist in my universe, I'm starting to wonder whether I have lost my marbles. Could some kind soul please point me in some sensible direction? cabal install xmonad-contrib Resolving dependencies... Configuring X11-xft-0.3... cabal: pkg-config version =0.9.0 is required but it could not be found. cabal: Error: some packages failed to install: X11-xft-0.3 failed during the configure step. The exception was: ExitFailure 1 xmonad-contrib-0.9.1 depends on X11-xft-0.3 which failed to install. cabal install x11-xft Resolving dependencies... Configuring X11-xft-0.3... cabal: pkg-config version =0.9.0 is required but it could not be found. cabal: Error: some packages failed to install: X11-xft-0.3 failed during the configure step. The exception was: ExitFailure 1 X11-xft version 0.9.0 doesn't even exist, as far a I can tell: 0.3 seems to be the highest. So what is making cabal believe that such a version is needed? Is it pkg-config? I'm not at all familiar with pkg-config, and, as far as I can tell it's not even installed on the Mac on which I am trying to do this. Curiously, its man page *does* work (it's in /usr/X11/man, for some reason). Does Cabal have some sort of embedded pkg-config? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal, xmonad-contrib, X11-xft, pkg-config ... questioning my sanity
Problem solved: 2 solutions described below. On 2010 Dec 6, at 14:15, Duncan Coutts wrote: On 6 December 2010 11:02, Jacek Generowicz jacek.generow...@cern.ch wrote: It a appears that a program which does not exist on my computer seems to insist on a package version which does not exist in my universe, I'm starting to wonder whether I have lost my marbles. Could some kind soul please point me in some sensible direction? cabal install xmonad-contrib Resolving dependencies... Configuring X11-xft-0.3... cabal: pkg-config version =0.9.0 is required but it could not be found. X11-xft version 0.9.0 doesn't even exist, as far a I can tell In the development version of cabal we have changed that error message to try and make it clear that it is looking for a program called pkg-config, not a Haskell package or a C lib. cabal: The program pkg-config version =0.9.0 is required but it could not be found. Do you think that message would have helped avoid your confusion? Oooh, that's a difficult question to answer, as I had read your earlier paragraph before coming to this question. After your explanation explained the error message (to the extent that I now wonder how on earth I ever took it to mean that it's looking for X11- xft version =0.9.0, when it quite clearly states pkg-config version =0.9.0 is required but could not be found), I have no idea whether the new message would have been better. Is there an alternative message that would have been better? Well, if I try to understand how I could have misunderstood the original message, I suspect that it is because of the common style of error message where the program generating the message precedes the actual message on the same line, just like cabal: ... precedes the message in this case. So I guess that I parsed it something like ... pkg-config: version =0.9.0 is required ... and inferred that 'version' refers to the package mentioned in an earlier message. In which case, maybe something like cabal: version =0.9.0 of pkg-config is required ... would have prevented me from making this particular mistake in this particular case. pkg-config [1] is a tool used by C libraries to describe things like dependencies on other C libs and what C compiler flags are needed to use the packages. The Haskell package X11-xft is a binding to the C library xft. On most modern unix systems xft C library provides meta-data that pkg-config can use. For example, on my system I can run: $ pkg-config --cflags xft -I/usr/include/freetype2 $ pkg-config --libs xft -lXft -lXrender -lfontconfig -lfreetype -lX11 Cabal does exactly the same thing, to work out what flags are needed to use the xft C library. The problem on your system is that the pkg-config program is not installed. Perhaps on OSX it comes with Xcode, I'm not sure. It may well also be the case that you don't have the development files for X11 or xft installed either (e.g. C header files). Hopefully some OSX person can advise you on what you need to install to do X11 development on OSX. Solution 1 (more complicated version): Although I never use XCode itself, I thought that I had it installed along with all the developer tools in order to get at GCC etc. Apparently not. Anyway, pkg-config seems to be available through darwinports, but I don't use darwinports (as, many years ago, I concluded that it's more trouble than it's worth, because of the strange places where it puts the stuff it manages). However, a plain manual compilation Just Works (for me): curl http://pkgconfig.freedesktop.org/releases/pkg-config-0.25.tar.gz -o pkgconfig.tgz tar zxf pkgconfig.tgz cd pkgconfig.tgz ./configure make sudo make install and I now have pkg-config If I try pkg-config --cflags xft it complains about the package not being found, and mentions the relevant environment variable. I *do* have /usr/X11/lib/pkgconfig/xft.pc, and popping its directiory into PKG_CONFIG_PATH makes the above pkg-config call now work. In this state, cabal install xmonad-contrib also works. = = = Solution 2 (simpler): I did manage to get xmonad-contrib to cabal install (without pkg- config) by asking for it not to use xft cabal install xmonad-contrib --flags=-use_xft Presumably cabal uses pkg-config for only a subset of the things it manages, and xft is the only one of those on which xmonad-contrib depends. Thank you Duncan for your concise, clear and complete answer: it was just what I needed to unblock me. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal, xmonad-contrib, X11-xft, pkg-config ... questioning my sanity
On 2010 Dec 6, at 15:05, Antoine Latter wrote: On my Mac 'which -a pkg-config' returns: /opt/local/bin/pkg-config /opt/local/bin/pkg-config I'm not sure why it prints twice. Same happens with my hand-installed version when I use the -a flag: it only shows it once when invoked without -a. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal, xmonad-contrib, X11-xft, pkg-config ... questioning my sanity
On 2010 Dec 6, at 15:39, Jacek Generowicz wrote: On 2010 Dec 6, at 14:15, Duncan Coutts wrote: In the development version of cabal we have changed that error message to try and make it clear that it is looking for a program called pkg-config, not a Haskell package or a C lib. cabal: The program pkg-config version =0.9.0 is required but it could not be found. Do you think that message would have helped avoid your confusion? Oooh, that's a difficult question to answer, as I had read your earlier paragraph before coming to this question. After your explanation explained the error message (to the extent that I now wonder how on earth I ever took it to mean that it's looking for X11- xft version =0.9.0, when it quite clearly states pkg-config version =0.9.0 is required but could not be found), I have no idea whether the new message would have been better. Is there an alternative message that would have been better? Well, if I try to understand how I could have misunderstood the original message, I suspect that it is because of the common style of error message where the program generating the message precedes the actual message on the same line, just like cabal: ... precedes the message in this case. So I guess that I parsed it something like ... pkg-config: version =0.9.0 is required ... and inferred that 'version' refers to the package mentioned in an earlier message. In which case, maybe something like cabal: version =0.9.0 of pkg-config is required ... would have prevented me from making this particular mistake in this particular case. Another thing that would probably have made it easier to understand: the message is strictly correct, but is *too* specific: it talks about pkg-config version =0.9.0 not being found, while the problem was that *no version at all* was present. I would understand if making the error message change according to such subtle distinctions would be more effort that it is worth. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cabal, xmonad-contrib, X11-xft, pkg-config ... questioning my sanity
On 2010 Dec 6, at 16:25, Duncan Coutts wrote: Perhaps something like this would be better: cabal: The program 'pkg-config' is required but it could not be found on the system (version 0.9.0 or later of pkg-config is required). That looks pretty good. I'm having trouble finding any holes in it. There is also the issue (if my understanding is correct) that cabal install only needs pkg-config for some packages. So it is possible that someone has happily been using cabal install for some time, and then suddenly it doesn't work. And then they are left wondering what broke: But I'm sure it worked last week, and I haven't changed anything etc. At which point it could be helpful to be told that it's a circumstantial rather than a fundamental problem. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Generating random tuples
I'm toying with generating random objects (for example tuples) and started wondering what pearls of wisdom Cafe might have on the matter. Two obvious points (relating to my toy code, shown below) are 1) The meaning of the limits required by randomR is not obvious for types such as tuples (you could come up with some definition, but it wouldn't be unique: how would you allow for different ones?[*]; you might decide that having such limits is nonsensical and not want to provide a randomR: would you then leave it undefinded?). [*] I guess this is related to issues such as Num being both a sum and and product monoid. 2) I'm sure there are at least half a dozen prettier definitions of random. But I suspect that the juicy bits will be in offerings about issues that I haven't even dreamed about. Presumably QuickCheck's test-data generation mechanism would be interesting to look at in this context. Is there a gentle explanation of how it works somewhere? Here's my initial effort: import Control.Monad import System.Random main :: IO (Int, Int) main = randomIO instance (Random a, Random b) = Random (a, b) where randomR = undefined random g0 = let (i1,g1) = random g0 (i2,g2) = random g1 in ((i1,i2), g1) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Golfing parsec code
I'm trying to write a utility which is able to read Ratios from two distinct formats 2 / 3 - 2 % 3 4 - 4 % 1 I'm sure that a skilled Haskell programmer could vastly improve on my code (do I even need Parsec?), so I've come to solicit advice. import Text.ParserCombinators.Parsec import qualified Text.ParserCombinators.Parsec.Token as P import Text.Parsec.Language (haskellDef) import Data.Ratio readFraction :: String - Either ParseError (Ratio Integer) readFraction = parse ratio - lexer = P.makeTokenParser haskellDef integer = P.integer lexer natural = P.natural lexer whiteSpace = P.whiteSpace lexer ratio = try frac | integer' integer' = do i - integer return $ fromInteger i frac = do whiteSpace num - natural char '/' den - integer return (num % den) f = readFraction 3 / 2 i = readFraction 6 main = print [f,i] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Increasing number of parameters
Thanks Brandon! I really like the addParam utility, value val prompt = Question prompt (show val) (readCheck val) addParam :: (Show a) = (funTy - String - qty) - (a - funTy) - String - (a - qty) addParam qmakr fun string v = qmakr (fun v) (string++ ++show v) prefix1 = addParam value prefix2 = addParam prefix1 prefix3 = addParam prefix2 but my crusty and sleep-deprived brain is not really grokking the internal plumbing. So I'm trying to get to grips with a simpler variation on the same theme, and I'm still failing. I'm trying to write something along the lines of addArg :: nArgFn - a - nPlus1ArgFn addArg fn a = (a+) fn where = something which applies its right parameter to however many arguments it needs and feeds the result to the left parameter in order to allow me to say sum2 = (+) sum3 = addArg sum2 sum4 = addArg sum3 etc. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Increasing number of parameters
On 2010 Oct 15, at 11:53, Kevin Jardine wrote: Jacek, I haven't been following this thread in any detail, so I apologise if I misunderstand your goal, My goal (in this thread, at least) is to become a better Haskell programmer, rather than to actually write any specific program. Yes, there are specific goals cited as examples, but the overall purpose is the journey, rather than the destination: I want to learn to walk and to run, rather than to get anywhere, just yet. but the ctm function in the polyToMonoid library (which maps its parameters to any specified monoid) appears to work in just this way. Yes, I noticed your earlier announcement. Yes, I recognized that it's pertinent to my last message. Yes, I've stored it in my (rapidly growing) list of things that Haskell Cafe has thrown at me that I should look into more deeply :-) But my current short-term goal is to understand the plumbing in a function that Brandon supplied, and to acquire the ability to write this kind of function myself in my sleep, with my hands tied behind my back, while the walls are falling all around me. At the moment I'm not managing to write it at all :-( It keeps consuming parameters until you hand it to the trm function to deliver the final result. More documentation here: Sounds a bit like the scheme I use for curried functions in Python. Though in Python I also have the option of calling the function with zero arguments to indicate termination, rather than terminating more explicitly by giving it to a terminate function. (Curried functions in Python? Can you tell that there's a Haskell programmer dying to get out ? :-) I've thrown in an example at the end, in case anybody is interested. http://hackage.haskell.org/packages/archive/polyToMonoid/0.1/doc/html/Data-PolyToMonoid.html It's already in my bookmarks, but thanks for taking the time to bring it to my attention. === from functools import partial def curry(fn): Function decorator. Curries its argument. The curried version collects all positional and keyword arguments it is given, until it is called with an empty argument list, at which point it applies the function to all the collected arguments. def curried_function(*args, **kwds): if not (args or kwds): return fn() else: it = partial(fn, *args, **kwds) try: it.__name__ = fn.__name__ except AttributeError: pass return curry(it) try: curried_function.__name__ = fn.__name__ + ' (curried)' except AttributeError: pass curried_function.fn = fn return curried_function @curry def collect(*args, **kwds): return I've collected: %s %s % (args, kwds) print collect# function collect (curried) at 0x712db0 print collect(1) # function collect (curried) at 0x712d30 print collect(1)(2,3,c=4)# function collect (curried) at 0x712bf0 print collect(1)(2,3,c=4)() # I've collected: (1, 2, 3) {'c': 4} ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
Using Brandon's code as a starting point (as it's far neater than mine), let's try asking some questions about fractions (I've included the whole program at the end). questions = [ addition 1 2, addition (1%2) (1%3) ] This works, but the the fractions are shown as 1 % 2 and to make it presentable to non-Haskellers, we have to change that to 1/2. In order to do this, I tried to replace show with my own version which I call view (in type class View). At this point I get ../arithmetic/hackBrandon.hs:63:23: Ambiguous type variable `t' in the constraints: `Num t' arising from the literal `1' at ../arithmetic/hackBrandon.hs:63:23 `View t' arising from a use of `addition' at ../arithmetic/hackBrandon.hs:63:14-25 `Read t' arising from a use of `addition' at ../arithmetic/hackBrandon.hs:63:14-25 Probable fix: add a type signature that fixes these type variable(s) My problem is that I don't see where I could add a type signature, but still keep addition :: a - a - Question polymorphic. === Here's the code demonstrating the problem = {-# LANGUAGE NoMonomorphismRestriction #-} import System.IO (hFlush, stdout) import Data.Ratio data Result = Correct | Improve String | Huh String | Incorrect String deriving Show data Question = Question { ask:: String , answer :: String , check :: String - Result } bool2result True = Correct bool2result False = Incorrect readCheckBy :: (Read a) = (a - Bool) - String - Result readCheckBy pred str = case reads str of [(val,)] - bool2result (pred val) _ - Huh readCheck :: (Read a, Eq a) = a - String - Result readCheck v s = readCheckBy (==v) s -- customized show class View a where view :: a - String instance View Int where view = show instance (Integral n) = View (Ratio n) where view = show -- helpers value val prompt = Question prompt (view val) (readCheck val) infix2 op symbol a b = value (op a b) (unwords [view a, symbol, view b]) addParam :: (View a) = (funTy - String - qty) - (a - funTy) - String - (a - qty) addParam qmakr fun string v = qmakr (fun v) (string++ ++view v) prefix1 = addParam value prefix2 = addParam prefix1 prefix3 = addParam prefix2 -- question 'types' addition = infix2 (+) + questions = [ addition 1 2 , addition (1%2) (1%3) ] test :: Question - IO () test q = do putStr $ ask q ++ = hFlush stdout reply - getLine putStrLn $ show $ check q reply main = mapM_ test questions ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 15, at 13:32, Jacek Generowicz wrote: questions = [ addition 1 2, addition (1%2) (1%3) ] My problem is that I don't see where I could add a type signature, but still keep addition :: a - a - Question polymorphic. Well, OK, I could write addition 1 (2 :: Int) inside the question list, but that's rather ugly, and it would be immensely annoying to have to do this for every specific question. Is there anywhere else it could go ? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Increasing number of parameters
On 2010 Oct 15, at 11:38, Jacek Generowicz wrote: [...] So I'm trying to get to grips with a simpler variation on the same theme, and I'm still failing. I'm trying to write something along the lines of addArg :: nArgFn - a - nPlus1ArgFn addArg fn a = (a+) fn where = something which applies its right parameter to however many arguments it needs and feeds the result to the left parameter in order to allow me to say sum2 = (+) sum3 = addArg sum2 sum4 = addArg sum3 etc. -- OK, I've understood. -- You use an accumulator to keep track of what has been done with the -- arguments that have been seen so far, and addArg takes one more -- argument, each time, and mixes it in with what is already there. -- I smell a monad. addArgSum :: (Num a) = (a - t) - a - a - t addArgSum fn acc arg = fn (acc + arg) sum1' = id sum2' = addArgSum sum1' sum3' = addArgSum sum2' -- And here's a more general version. addArg combine fn acc arg = fn (combine arg acc) sum1 = id sum2 = addArg (+) sum1 sum3 = addArg (+) sum2 sum4 = addArg (+) sum3 -- But I don't really get why the following leads to complaints about -- infinite types. -- sumN n = iterate (addArg (+)) id ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Ambiguous type variable
-- Given a definition of view which is essentially a synonym for show: class View a where view :: a - String instance View Int where view = show -- why does show 2 compile, while view 2 gives an -- 'Ambiguous type variable' error fine = view (2::Int) noProblem = show 2 ambiguousTypeVariable = view 2 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Ambiguous type variable
On 2010 Oct 16, at 00:51, Ivan Lazar Miljenovic wrote: On 16 October 2010 09:47, Jacek Generowicz jacek.generow...@cern.ch wrote: -- Given a definition of view which is essentially a synonym for show: class View a where view :: a - String instance View Int where view = show -- why does show 2 compile, while view 2 gives an -- 'Ambiguous type variable' error fine = view (2::Int) noProblem = show 2 ambiguousTypeVariable = view 2 2 is a generic number. If you don't specify a type, it usually defaults to Integer. All Num instances that come in the Prelude have Show instances, so no matter which gets picked show 2 works. However, when you say view 2 ghc/ghci doesn't know that you want 2 to be an Int (as that's the only type you have an instance for View for). Which implies that defining all instances of Num to be instances of View should do the trick, and that doesn't seem to work. See below. On 2010 Oct 16, at 00:51, Christopher Done wrote: Don't integral literals default to Integer, of which there is a Show instance but no View instance? Hmm, it doesn't seem to be that simple. The phenomenology seems to be: As far as entering view 2 into ghci is concerned, you need 'instance View Integer' or 'instance View Double'. To get x = view 2 to compile in ghc, having all of Int, Integer, Float and Double as instances of View is still not enough. I did all this in an environment where I had not imported any other Num instances, and :i Num in ghci showed only the 4 aforementioned types as instances. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Ambiguous type variable
On 2010 Oct 16, at 01:14, Jacek Generowicz wrote: On 2010 Oct 16, at 00:51, Ivan Lazar Miljenovic wrote: 2 is a generic number. If you don't specify a type, it usually defaults to Integer. All Num instances that come in the Prelude have Show instances, so no matter which gets picked show 2 works. However, when you say view 2 ghc/ghci doesn't know that you want 2 to be an Int (as that's the only type you have an instance for View for). On 2010 Oct 16, at 00:51, Christopher Done wrote: Don't integral literals default to Integer, of which there is a Show instance but no View instance? An in both of the explanations above, it should then complain about the lack of an instance of View, rather than about ambiguous type variables, n'est-ce pas? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Ambiguous type variable
jacek.generow...@cern.ch wrote: -- Given a definition of view which is essentially a synonym for show: class View a where view :: a - String instance View Int where view = show -- why does show 2 compile, while view 2 gives an -- 'Ambiguous type variable' error fine = view (2::Int) noProblem = show 2 ambiguousTypeVariable = view 2 On 2010 Oct 16, at 01:25, Daniel Fischer wrote: http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-790004.3.4 Defaulting only takes place when all involved classes are defined in the Prelude or the standard libraries. Your View class isn't, hence there's no defaulting. Bingo. Thank you. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Ambiguous type variable
On 2010 Oct 16, at 01:39, Daniel Fischer wrote: On Saturday 16 October 2010 01:18:55, Jacek Generowicz wrote: On 2010 Oct 16, at 01:14, Jacek Generowicz wrote: On 2010 Oct 16, at 00:51, Ivan Lazar Miljenovic wrote: 2 is a generic number. If you don't specify a type, it usually defaults to Integer. All Num instances that come in the Prelude have Show instances, so no matter which gets picked show 2 works. However, when you say view 2 ghc/ghci doesn't know that you want 2 to be an Int (as that's the only type you have an instance for View for). On 2010 Oct 16, at 00:51, Christopher Done wrote: Don't integral literals default to Integer, of which there is a Show instance but no View instance? An in both of the explanations above, it should then complain about the lack of an instance of View, rather than about ambiguous type variables, n'est-ce pas? Non. If you write x = view 2 the type checker looks at the expression 2 and it sees it has the type Num a = a (because integer literals are actually shorthand for (fromInteger literal) and fromInteger :: Num a = Integer - a). Then (or before that) it looks at the context in which the 2 appears. That context is that the function view is applied to it. view :: View v = v - String So, in order for the expression 2 to be well typed, the type checker finds the two constraints 2 :: Num a = a 2 :: View v = v These constraints have to be unified (which is very easy here), resulting in 2 :: (Num a, View a) = a But there's no way to find out what type a is/has to be. Hence a is an ambiguous type variable. Exactly. Which is why I made the point that the two explanations offered by Christopher and Ivan (both of which suggested that the problem was related to a missing View instance) imply that the error report should mention missing View instances: As the error message does not mention them, I took this as further evidence that those suggestions were not correct. Now, under certain circumstances such ambiguous type variables are resolved by defaulting. If you replace view with show, you get a Show constraint instead of the View constraint and then defaulting may (and must) happen. But since View is defined outside the standard libraries, the language report says defaulting mustn't take place, so it doesn't Yup. That much was clear from you last message. (it may work if you specify {-# LANGUAGE ExtendedDefaultRules #-} at the top of your module). Interesting. Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 14, at 05:27, Brandon Moore wrote: If you just want instances of questions you can keep it simple. How about something isomorphic to data Instance = Instance { question : String, answer : String, check : String - Bool } At first blush, I hated all those Strings hiding the actual type information. Thinking about it a bit more, I think that's exactly right: when crossing the interface to the outside world, all data have type String: the user reads Strings and types back Strings. A variety of things happens behind those strings, but at the interface, they're all strings. You could make helper functions similar to your old code, like addition : (Int , Int) - Instance You might handle problem families by taking a random number generator, or maybe using QuickCheck's Gen monad. Oh, I love the idea of Using QuickGen's Gen for this purpose! (And it would finally give me the incentive to get to understand the beast properly.) easyMultiplication : Gen Instance ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 14, at 05:39, Brandon Moore wrote: On Oct 13, 2010, at 7:44 PM, Jacek Generowicz jacek.generow...@cern.ch wrote: On 2010 Oct 14, at 01:32, Evan Laforge wrote: I think I'm starting too see what my problem is. I think it boils down to hankering for Duck Typing and variadic functions. I fully appreciate that passing functions is a wonderful and powerful technique for catering for variation, but Haskell's type system cramps my style by insisting that I can't put a (Banana - Cake) in the same container as an (Octopus - Truffles - DogsBreakfast). But the thing is, I don't use things like this, even in python. Shame. They're damn useful :-) How are you expecting to call the functions in that container? for f in c: try: return f(*misc_args) except: pass? to_do = [(call, (AuntMabel,)), (buy, ([(12*kg, sugar), (6*bushel, wheat)])), (introduce, (Romeo, Juliet))] for do,it in to_do: do(*it) What is the point of doing that? If it's just to defer execution until that loop, you should just rely on lazy evaluation, or [IO ()]. There's more to it than that: The point is to treat combinations of functions and other data (which may or may not come from different sources, but are brought together to make a coherent whole) as entities which are allowed to reside in the same variable or the same container. Those other data might be the functions' arguments, or they might be other functions with which they are to be combined, or both. Here's an example where lazy evaluation isn't enough: def memoize(fn): cache = {} def memoized_fn(*args): if args not in cache: cache[args] = fn(*args) return cache[args] return memoized_fn You memoize a function once, but it will be given different arguments, many times, at a later time. But what should the type of fn be? What should the type of args be? In Python, I don't care, as long no type error occurs when they are combined thus: fn(*args) How do you let Haskell type check the combination of the types, rather than the individual types? My answer seems to be: define a variant type for holding the combinations. The problem with this is that the set of allowed combinations is closed at library compile time. I want it to remain open for extension. In Duck Typing this happens trivially. If that's not the only thing you do, then the question is still how you know enough about the structure of values In the list to do anything useful with them. There is a constraint on the *combination* of their types, while allowing the individual types to vary within that constraint. This constraint defines what I can do with them. Though, in practice, what I want to do with them defines the constraint. (I guess that looking at how memoization is done in Haskell might teach me something relevant.) I suppose you haven't heard of parametricity theorems. You suppose correctly :-) In Haskell, values have no hair. If you don't know anything about the type of a values you can't inspect it. It's one of the major tools that helps type signatures contribute to the correctness of implementations. In Python, Java, and other similar languages there are lots of things you can do with unknown values - get a string representation, test for equality with another value, get the class it belongs to, etc. So, we won't understand the point of your example without a little more information on what you do to those heterogeneous values, and how the program can tell which things to do wi which item, Another example: Let's say I need an Int - String. Both (fnA2 :: Banana - String) . (fnA1:: Int - Banana) and (fnB2 :: Onion - String) . (fnB1 :: Int - Onion) will do. So please allow me to store (fnA1, fnA2) and (fnB1, fnB2) in the same place. The program can tell that it can combine them with (.) because the type of let (fn1, fn2) = pair in fn2 . fn1 is always Int - String. The whole thing could be summarized by saying: Please type check the whole, not the individual parts; let me store the parts in the same place. In Haskell it may be fun to turn on -XGADTs and write Now you're just trying to burst my todo list, aren't you :-) data DelayedApp result where Base :: a - DelayedApp a App :: DelayedApp (a - b) - a - DelayedApp b but it turns out to be isomorphic to data DelayedResult r = DR a Nat - at least until you add some more data to the constructors. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 14, at 09:19, Evan Laforge wrote: How are you expecting to call the functions in that container? for f in c: try: return f(*misc_args) except: pass? to_do = [(call, (AuntMabel,)), (buy, ([(12*kg, sugar), (6*bushel, wheat)])), (introduce, (Romeo, Juliet))] for do,it in to_do: do(*it) As has been pointed out, simply write it like this: to_do = [call AuntMabel, buy [(12kg, sugar), (6 bushel, weat)], etc.] Which works for this case, but not in general. For example here's the memoizer example I used in response to Brandon: def memoize(fn): cache = {} def memoized_fn(*args): if args not in cache: cache[args] = fn(*args) return cache[args] return memoized_fn You memoize a function once, but it will be given different arguments, many times, at a later time. But what should the type of fn be? What should the type of args be? In Python, I don't care, as long no type error occurs when they are combined thus: fn(*args) How do you let Haskell type check the combination of the types, rather than the individual types? My answer seems to be: define a variant type for holding the combinations. The problem with this is that the set of allowed combinations is closed at library compile time. I want it to remain open for extension. In Duck Typing this happens trivially. If they are monadic actions, you can call 'sequence_' on them when you want them to happen. If not, you really just have a list. The thing is, I can arrange for them to be compatible. Python won't be able to confirm this statically, but is it too much to ask of Haskell to have it figure out (statically) that all of (Int - Bool, Int) (Banana - Apple - Orange - Kiwi - Bool, (Banana, Apple, Orange, Kiwi)) (Bool - Bool - Bool, (Bool, Bool)) can be combined to give Bool ? Yes, this sounds like an existential: data Boolable forall a. = Boolable (a - Bool) But despite the fact that I've been keeping them in the back of my mind for years, I've never once come up with a place where one would actually be useful. I guess I just don't think that way. I think that Haskell allows so many completely different approaches to things, that serious Haskell programmers are essentially using completely different languages which share a small common core :-) I agree with you that this is sometimes easier in a dynamic language because you can reuse the implementation language at runtime. I don't think I'm looking for that in this case. I'm just asking to be allowed to stick both (A - B - X, (A, B)) and (C - D - E - X, (C, D, E)) etc. in the same container, because, frankly, in the context in which they are used, they *are* the same. Maybe you should focus less on the particular implementation you want and more on the end result? If you start off saying I want heterogenous lists then you'll start off with a problem for haskell :) Of course. Please don't get the impression that I'm trying to fit things into my box and won't accept anything else. I'm here to learn. In the process of explaining what I mean in some particular case, I end up using language from which says that I want this, but that only refers to the exploration of one particular approach. I am open to, and eagerly encourage, completely different suggestions. Haskell doesn't have the interpreter around at runtime. But if you know exactly what parts of the interpreter you want, you can recover them, i.e. with Dynamic or by using 'hint' in the extreme. Hint. Hmm. Embedding an interpreter into your code. I can imagine lots of interesting uses for this. But I don't think I want/need it in this case. Thanks for pointing it out, though. apply1 f [x] = f x apply1 _ _ = throw hissy fit apply2 f [x, y] = f x y etc. I would hope that the types could be checked statically, as I explained above. They can. The strings coming in from the user, of course they can't, Sure, but that's why we have a ParseError constructor in our Question type. because they're not even known statically. The 'apply1' function, of course, is statically checked in that 'f' is required to be a function with a single string argument. Well, of the same type as the list passed. But I feel rather cramped by x and y in apply2 being constrained to having the same type. I'm pretty sure that you could never come up with a sufficiently large set of primitives. Even if you could, it seems like far too much work, given that the ability to store arbitrary (sets of co-operating) functions (which, together, always return the same types) in the same container, trivially provides you with full generality. Could you provide a more concrete example? So far the simple example of int accepting functions with different arities is pretty easy to implement with a plain list, Trivial, as long as you combine the components immediately. If you need to
Re: [Haskell-cafe] Client-extensible heterogeneous types
[Gregory: Sorry about duplicate, accidentally took it off-list.] On 2010 Oct 14, at 09:46, Gregory Collins wrote: Jacek Generowicz jacek.generow...@cern.ch writes: Could you explain this a bit more? heterogeneousProcessor was extremely boring: its only interesting feature was the dot between datum and method() Here it is again: def heterogeneousProcessor(data): return [datum.method() for datum in data] Typically we use an existential type for this: {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE RankNTypes #-} data A = A data B = B class HasFooMethod a where foo :: a - String instance HasFooMethod A where foo _ = This is A's foo method instance HasFooMethod B where foo _ = This is B's foo method data SomeFoo = forall a . (HasFooMethod a) = SomeFoo a printFoo :: SomeFoo - IO () printFoo (SomeFoo x) = putStrLn $ foo x -- main :: IO () main = do let foos = [SomeFoo A, SomeFoo B, SomeFoo A] mapM_ printFoo foos Running main: *Main main This is A's foo method This is B's foo method This is A's foo method Yes, I've now understood that ExistentialQuantification can help with this, and I've even got as far coming up with almost exactly this example of its use. But it's good to have confirmation that I'm doing it right. So thanks for this code sample. There is more information about the different ways of doing this kind of thing in Haskell in the OOHaskell paper: http://homepages.cwi.nl/~ralf/OOHaskell/ Abstract looks good. On the one hand I want to explore how Haskell allows me to do things in a way that doesn't resemble OO at all. On the other, it's good to see how OO-like things might be done in Haskell. Unfortunately, this model of programming is a little awkward in Haskell which is why (for the most part) it isn't used as much as it could or should be. N.B. that the Control.Exception module from the standard library (from GHC 6.8 on at least) uses this technique to provide extensible exceptions. Hope this helps, Yes. Thanks. Only problem is, that you (plural) have, in about half-a-dozen responses, given me sufficient food for thought to occupy my brain for the next couple of months! :-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 14, at 09:54, Joachim Breitner wrote: Hi, Am Donnerstag, den 14.10.2010, 09:34 +0200 schrieb Jacek Generowicz: Another example: Let's say I need an Int - String. Both (fnA2 :: Banana - String) . (fnA1:: Int - Banana) and (fnB2 :: Onion - String) . (fnB1 :: Int - Onion) will do. So please allow me to store (fnA1, fnA2) and (fnB1, fnB2) in the same place. The program can tell that it can combine them with (.) because the type of let (fn1, fn2) = pair in fn2 . fn1 is always Int - String. This is possible: {-# LANGUAGE ExistentialQuantification #-} Existential Quantification yet again! I see that its status in Haskell Prime is None. Anybody care to hazard a guess as to the odds of its acceptance? Which implementations support it today ? data SplitFun a b = forall x. SplitFun (a - x, x - b) splitFuns :: [SplitFun Int String] splitFuns = [SplitFun (\n - replicate n hi, concat) ,SplitFun (show, id)] And x might be a function type (with any number of arguments), so we get some variadicity for free! I hadn't thought of that. That's brilliant. main = mapM_ putStrLn $ map (\(SplitFun (f1,f2)) - f2 (f1 2)) splitFuns This prints: *Main main hihi 2 Brilliant. Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 14, at 09:56, Max Bolingbroke wrote: On 14 October 2010 08:34, Jacek Generowicz jacek.generow...@cern.ch wrote: Those other data might be the functions' arguments, or they might be other functions with which they are to be combined, or both. You can represent these as existential packages. However, as Oleg shows you can always use skolemisation to eliminate the existential: http://okmij.org/ftp/Computation/Existentials.html This trick is basically what Brandon and Evan pointed out earlier when they suggested you replace the list :: [exists b. (b - a, b)] with a list :: [a]. Aaah. The link between the last two paragraphs is important. Thanks very much. Here's an example where lazy evaluation isn't enough: def memoize(fn): cache = {} def memoized_fn(*args): if args not in cache: cache[args] = fn(*args) return cache[args] return memoized_fn You memoize a function once, but it will be given different arguments, many times, at a later time. I'm not sure why you would use existentials for this. Isn't the type of memoized_fn just :: Ord a = (a - b) - a - b? I don't think so. The Python Duck Type of memoized_fn (and fn), expressed in Haskell syntax is a - b | a - b - c | a - b - c - d | etc. The type of memoize would be (a - b) - a - b | (a - b - c) - a - b - c | (a - b - c - d) - a - b - c - d | etc. Which is the whole point of the * in *args. (Not sure why you specified Ord a. In Python you *would* need Hashable a,b,c,d.) Of course, you could argue that the type is (a - b) - a - b | (a - b - c) - (a, b) - c | (a - b - c - d) - (a, b, c) - d | etc. But does that change things significantly? This doesn't deal with argument *lists* so you may have to curry/uncurry to get functions of a different arity to go through, but that is IMHO a reasonable requirement for Haskell, where multi-argument functions do not have special status. I would argue that easily dealing with different arities is an important requirement of the arithmetic test motivating example. (In the absence of side effects, I can't see an obvious way to implement it without some way to enumerate the domain a though. Conal Elliot uses type classes to solve this issue, see http://hackage.haskell.org/package/MemoTrie, where memo :: HasTrie t = (t - a) - t - a). Thanks for the heads-up. will do. So please allow me to store (fnA1, fnA2) and (fnB1, fnB2) in the same place. The program can tell that it can combine them with (.) because the type of But if the only operation you ever do on this pair is (.), you may as well skolemise and just store (fnA1 . fnA2) directly. What is the advantage of doing otherwise? (.) is not the *only* operation I will do. But I think that's a red herring. Regardless of what operation I will do, I think that the problem is that some of the components are known earlier than others. But I think that currying trivially solves this particular problem. So I think that, as you say, skolemisation will do the trick. Though I still haven't delved sufficiently into the article you cite at the top, to be sure that extensibility won't be curtailed by this approach. If it is, then existentials should do the job. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 14, at 09:58, Ketil Malde wrote: Jacek Generowicz jacek.generow...@cern.ch writes: Let's say I need an Int - String. Both (fnA2 :: Banana - String) . (fnA1:: Int - Banana) and (fnB2 :: Onion - String) . (fnB1 :: Int - Onion) will do. So please allow me to store (fnA1, fnA2) and (fnB1, fnB2) in the same place. I think you can do this fairly easy with existentials, but.. Yup, that's got through to me by now :-) The program can tell that it can combine them with (.) ..what else do you want to be able to do with them? (Because, if this is all, you'd just store the combination, no?). Yes, if the components became available at the same time. But they don't. However, I think that currying caters for this separate arrival time problem. Hmm, except that I would like to be able to store a collection of incomplete combinations and say complete the combination by injecting random arguments of the relevant type. (This probably won't make sense unless you saw the arithmetic test motivating example.) And currying can't deal with this, as the *incomplete* combinations will have different types. But I suspect that Brandon's suggestion to use QuickCheck's Gen monad, could well help with this. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 14, at 15:24, Ketil Malde wrote: Jacek Generowicz jacek.generow...@cern.ch writes: def memoize(fn): cache = {} def memoized_fn(*args): if args not in cache: cache[args] = fn(*args) return cache[args] return memoized_fn Here's a simplified memoizer for Haskell: memoize :: (Integral t) = (t - a) - t - a memoize f = ([f i | i - [0..]]!!) . fromIntegral This is a very cute snippet, but I think that its cuteness circumvents the whole point of the Python code, which was to demonstrate how heterogeneous duck-typed values can be used safely. The Python memoizer memoizes functions of *any* type: yours allows very limited heterogeneity, so I'm failing to see how it addresses the issue. But what should the type of fn be? What should the type of args be? The args to fn must be of a type that is indexable by the memoizing structure. My example is simplistic, and will only memoize functions where the first argument is a integral, non-negative number, and it uses a list (with O(n) access), but you can probably improve it as you see fit. I think that now we're starting to concentrate on the memoizer in particular, rather that the more general issue that the memoizer was meant to exemplify. I think this will work for multi-parameter functions too, because of currying. In Python, I don't care, as long no type error occurs when they are combined thus: fn(*args) In Haskell, the type of 'memoize g' is the same as 'g', so you don't have to care - the compiler cares for you. :-) Same in Python (except that the run-time cares for you, rather than the compiler). But in Haskell it sometimes also cares about fn and args separately, even when it shouldn't. My questions are about persuading it that it shouldn't. Perhaps I'm missing something obvious? I think that what you might have missed is that the only interesting type is that of fn(*args): that I don't care about the type of fn on its own, or the type of args on its own, but that together they make up whatever type is required. And that Haskell's type system gets in the way by insisting on checking the types of fn and args separately; while Python's gets out of the way, by only caring when the two are brought together and actually *used*. But maybe it is I who has missed you addressing this point. Either way, I think that pursuing the memoizer any further (interesting though it is in its own right) takes us too far off track. I think that the answer (well, one important answer) to my earlier question is: a) Existential Quantification allows you to do this. b) Skolemization allows you to do this without the Existential Quantification extension. From what little I've read around this subject, it seems that considerations similar to the ones I'm talking about are repeatedly used as motivations for Existential Quantification, so I'm pretty confident that I'm not completely full of crap; or if I am, then I'm in good company :-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
Thank you all for your contributions so far. Plenty of food for thought. I though I'd try to put it into practice and have a go at the motivating example I gave: essentially a EDSL for defining simple maths tests. I've included the beginnings of an attempt at the end. It started promisingly. As long as I stuck to binary operators over integers, everything went smoothly, and adding new question types was a joy. The first annoyance comes when adding the first unary operation into the set of questions. Then I was forced to duplicate make into make1 and make2: essentially identical functions, differing only in the number of arguments they take. This sort of copy-paste programming really annoys me, but I can live with it in this case, as the duplication will only be in one dimension (operator arity), and concerns only one function. But it all goes pear shaped as soon as I try to cater for questions dealing with fractions, for example: Now the type system requires me to duplicate all the question-making utilities and give them different names. I tried to mitigate this by using type classes but got walloped by the No Monomorphism Restriction, and so on, and so forth. Wherever I turned, the type system was getting in the way. Looking at it another way, I have the Question type which can contain a sufficient variety of questions, but providing a set of utilities for conveniently populating the type, without excessive code duplication, is something that I am unable to do with Haskell's type system getting in the way. But I take this to be my shortcoming rather than Haskell's, so I would appreciate advice on how to proceed with this exercise. Code follows. Thank you all. == import System.IO (hFlush, stdout) data Result = Correct | Improve String | Huh String | Incorrect String deriving Show data Question = Question { ask:: String , answer :: String , check :: String - Result } bool2result True = Correct bool2result False = Incorrect -- askers infix2 sym a b = show a ++ ++ sym ++ ++ show b prefix1 sym a = sym ++ ++ show a prefix2 sym a b = sym ++ ++ show a ++ ++ show b -- checkers chk correct given = bool2result $ read given == correct -- makers make1 op symbol asker checker a = Question ask (show answer) check where ask = asker symbol a answer = op a check = checker answer make2 op symbol asker checker a b = Question ask (show answer) check where ask = asker symbol a b answer = op a b check = checker answer -- question 'types' addition = make2 (+) + infix2 chk subtraction= make2 (-) - infix2 chk multiplication = make2 (*) x infix2 chk power = make2 (^) ^ infix2 chk square = (flip power) 2 cube = (flip power) 3 square' = make1 (^2) square prefix1 chk questions = [ addition 1 2 , subtraction 3 2 , multiplication 4 5 , square 3 , cube 3 ] test :: [Question] - IO () test [] = return () test (q:qs) = do putStr $ ask q ++ = hFlush stdout reply - getLine putStrLn $ show $ check q reply test qs main = test questions ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types
On 2010 Oct 13, at 00:28, Alexander Solla wrote: On Oct 12, 2010, at 4:24 AM, Jacek Generowicz wrote: I can't see a Haskell solution which combines both of these orthogonal features without losing the benefits of the type system. (For example, I could create my own, weak, type system with tags to identify the type and maps to do the dispatch.) Is there any particular reason why you want to actually to mirror Python code? I don't want to: I merely have a situation in which an OO solution (not necessarily a good one) immediately springs to mind, while I didn't see any obvious way to do it in Haskell. (I am sure that this is my shortcoming, not Haskell's.) I included the Python example lest my question be too nebulous without it. I would be delighted to learn approaches which are completely different to anything offered by OO. In fact, for personal didactic purposes, being un-OO-like could even be considered to be a goal. I think that letting the programmer design domain specific control structures is rather the point of Haskell. While I don't, at the moment, understand exactly how this is the case, I do like the sound of it. Instead of relying on a one-sized fits all solution (which only really fits one kind of problem), you write your own. And it is typically easier to write the control structure than it is to implement it using the OO patterns, because of the notion of irreducible complexity. For example, the Factory pattern constructs a functor. You can write the essential semantics of doing this with a single Functor instance, instead of writing multiple classes which implement the semantics, while relying on implicit, and possibly ill- fitting semantics of method dispatch. The other OO patterns make this objection stronger. If you can write a UML diagram, you can turn it into a commutative diagram, and write less code by implementing its arrows. Lots of stuff that sounds fascinating, but whose detailed meaning is, at the moment, beyond my grasp. So let my start off by getting my teeth into your example code: An OO class hierarchy is a very specific functor over objects (which attaches methods to objects). This sounds very interesting, but, again, I'm having difficulty understanding *exactly* how that is. Haskell provides the Functor type class. Write your generic functions for specific functors: -- The varying input types. Will be attached to arbitrary values by the Functor instance. data A = A -- Variant 1 data B = B -- Variant 2 -- Some normalized Output type. data Output = Output -- The new control structure. data Attaches a = AttachesA A a | AttachesB B a -- Stick your conditional (varying) semantics in here. Corresponds to heterogeneousProcessor. Could you explain this a bit more? heterogeneousProcessor was extremely boring: its only interesting feature was the dot between datum and method() Here it is again: def heterogeneousProcessor(data): return [datum.method() for datum in data] I suspect that runAttaches is (potentially) a lot more interesting than that! -- The output presumably depends on whether A or B is attached, so this function is not equivalent -- to something of the form fmap (f :: a - Output) (attaches :: Attaches a) runAttaches :: Attaches a - Attaches Output runAttaches = undefined -- This corresponds roughly to heterogeneousProcessor(heterogeneousContainer): processedOutputs :: [Attaches a] - [(Attaches Output)] processedOutputs as = fmap runAttaches as Would it be correct to say that runAttaches replaces Python's (Java's, C++'s etc.) dynamically dispatching dot, but also allows for a greater variety of behaviour? Alternatively, would it be interesting to compare and contrast runAttach to CLOS' generic functions, or even Clojure's arbitrary method selection mechanism? -- Functor instance. Now you have a way to treat an (Attaches a) value just like you would an a. (modulo calling fmap) instance Functor Attaches where fmap f (AttachesA A a) = (AttachesA A (f a)) fmap f (AttachesB B a) = (AttachesB B (f a)) [ Aside: Briefly returning to my original question: I don't see how, if this were supplied in a library, it would allow clients to inject new entities into the framework. It all seems to hinge on the Attaches type, which would be defined in the library, and is not extensible without modifying the library source code (unless I'm missing something). Which doesn't diminish my desire to understand what you are saying, in the slightest. Can the set of variants usable in this framework be extended without modifying the original source? ] Coming back to your statement that An OO class hierarchy is a very specific functor over objects (which attaches methods to objects), how would we complete your code so that it implements this particular functor
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 13, at 23:52, Evan Laforge wrote: I admit I haven't read this whole thread in detail, but when I want something with an implementation that can vary dynamically I just pass a different function. Of course. Your original python example is equivalent to just passing strings in haskell, Sure. The original example was kept trivial, thereby hiding the true problem. so lets add an argument: type Process = Int - String heterogeneousProcessor :: [Process] - [String] heterogeneousProcessor ps = [p 42 | p - ps] -- or map ($42) ps variant1 n = variant1 stuff ++ show n -- etc. Now the user of your library can pass their own Process. Which works just fine, if all the different things I might wish to express can be expressed within (Int - String) (or any other function type). I have a number of records in my program like State { lookup_x :: Name - Maybe X, lookup_y :: Name - Maybe Y, do_something_important :: X - Result }. They reduce dependencies by not exposing the (complicated) lookup details and types, and aid testing because I can just pass a state with a dummy 'do_something_important' (in my case, it's update GUI, which is important to stub out for a test). I think I'm starting too see what my problem is. I think it boils down to hankering for Duck Typing and variadic functions. I fully appreciate that passing functions is a wonderful and powerful technique for catering for variation, but Haskell's type system cramps my style by insisting that I can't put a (Banana - Cake) in the same container as an (Octopus - Truffles - DogsBreakfast). I can get around this by creating a variant type which contains both of these (and any others I might ever need to use), but a) It's bloody tedious (compared to having to do exactly nothing in Duck Typing), b) The set of acceptable function types is not extensible by clients. Put another way, your X and Y types aren't flexible/large enough. This may be simpler than what you had in mind, but to narrow it down, could you provide a more specific example where this is inadequate? How about this? -- Imagine that I want to write a program which will help me practice -- basic arithmetic. -- At its core I might have the following three functions ask :: (Int, Int) - String ask (a,b) = show a ++ + ++ show b answer :: (Int, Int) - Int answer (a,b) = a + b check :: (Int, Int) - String - Bool check q ans = (read ans :: Int) == answer q -- which present the question, and check whether a given answer is -- correct. -- Now, imagine I've got addition down pat, and want to extend my -- repertoire to subtraction. I could introduce some flexibility into -- my core functions thus data Operation = Operation (Int - Int - Int) String ask' :: (Int, Int) - Operation - String ask'(a,b) (Operation _ sym) = show a ++ ++ sym ++ ++ show b answer' :: (Int, Int) - Operation - Int answer' (a,b) (Operation op _) = op a b check' :: (Int, Int) - Operation - String - Bool check' q op ans = (read ans :: Int) == answer' q op -- Now my program can deal with any binary infix operations on -- Ints. But what if I now want to practice a unary operation -- (e.g. sqrt)? How about a binary prefix one (e.g. gdc) ? -- Maybe this is the way forward? data Question = BinaryInfix (Int - Int - Int) String Int Int | BinaryPrefix (Int - Int - Int) String Int Int | UnaryPrefix (Int - Int)String Int ask'' :: Question - String ask'' (BinaryInfix _ sym a b) = show a ++ ++ sym ++ ++ show b ask'' (BinaryPrefix _ sym a b) = sym ++ ++ show a ++ ++ show b ask'' (UnaryPrefix _ sym a) = sym ++ ++ show a answer'' :: Question - Int answer'' (BinaryInfix op _ a b) = op a b answer'' (BinaryPrefix op _ a b) = op a b answer'' (UnaryPrefix op _ a) = op a check'' :: Question - String - Bool check'' q a = (read a :: Int) == answer'' q -- So far, so ... not too bad. -- I'm a little annoyed by the repetitive tedium of answer'': this -- will really wind me up when I get on to TernaryPrefix, -- QuaternaryPrefix etc. and I will hanker for something like Python's -- *args. -- Now, I go to a party and thoroughly impress my friends with my -- newly-acquired arithmetic wizardry. One thing leads to another and -- my program ends up in the hands of another soul or two, desperate -- to match my mental calculation powers: I acquire some users. And as -- every schoolboy knows, users are closely followed by feature -- requests. -- John wants to practice adding fractions. Cindy needs to learn to -- find all prime factors of a given number. -- Clearly -- -- check'' q a = (read a :: Int) == answer'' q -- -- won't cut the mustard any more. -- Now, I can't see any obvious reason why I can't just keep adding -- new constructors to Question, and corresponding patterns to ask, -- answer and check, but I'm a lazy bugger and want to palm this off -- onto the users by telling them that I am empowering them by giving -- them the
Re: [Haskell-cafe] Client-extensible heterogeneous types
On 2010 Oct 12, at 15:44, John Lato wrote: It's not plain Haskell, but I'm surprised nobody mentioned the ExistentialQuantification extension, which unless I'm missing something provides exactly what you want. Yes, it does appear to be *exactly* what I want. Thanks. (Now, how about those HLists?) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
On 2010 Oct 14, at 01:32, Evan Laforge wrote: I think I'm starting too see what my problem is. I think it boils down to hankering for Duck Typing and variadic functions. I fully appreciate that passing functions is a wonderful and powerful technique for catering for variation, but Haskell's type system cramps my style by insisting that I can't put a (Banana - Cake) in the same container as an (Octopus - Truffles - DogsBreakfast). But the thing is, I don't use things like this, even in python. Shame. They're damn useful :-) How are you expecting to call the functions in that container? for f in c: try: return f(*misc_args) except: pass? to_do = [(call, (AuntMabel,)), (buy, ([(12*kg, sugar), (6*bushel, wheat)])), (introduce, (Romeo, Juliet))] for do,it in to_do: do(*it) (Actually, it is far more commonly used in Python in all sorts of function wrappers. But the general principle is the same: It's somebody else's problem to ensure they give me compatible data, but the type system won't grumble about the types being different; it will only complain when the result of bringing the types together doesn't make sense. All at run-time, of course.) The thing is, I can arrange for them to be compatible. Python won't be able to confirm this statically, but is it too much to ask of Haskell to have it figure out (statically) that all of (Int - Bool, Int) (Banana - Apple - Orange - Kiwi - Bool, (Banana, Apple, Orange, Kiwi)) (Bool - Bool - Bool, (Bool, Bool)) can be combined to give Bool ? So, in my maths tester, I'm only ever going to stick together compatible versions of ask, answer and check, but in any given set, the types of the 3 functions will not be the same as those in any other set. At which point Haskell refuses to let me store them in the same container. (Without existential types, at least.) data Question = BinaryInfix (Int - Int - Int) String Int Int | BinaryPrefix (Int - Int - Int) String Int Int | UnaryPrefix (Int - Int)String Int Well, you're creating a little interpreter here. Yes, this can be viewed as an interpreter for maths testing language. I agree with you that this is sometimes easier in a dynamic language because you can reuse the implementation language at runtime. I don't think I'm looking for that in this case. I'm just asking to be allowed to stick both (A - B - X, (A, B)) and (C - D - E - X, (C, D, E)) etc. in the same container, because, frankly, in the context in which they are used, they *are* the same. In the extreme, in python, you can simply call eval() on the input string. Aaaargh! No! For the love of all that is good, please! No! :-) But seriously, there's enough dynamism, introspection etc. in Python, that eval is almost completely avoidable. I've used it once, in a situation where faking up a Lisp macro turned out to be an order of magnitude simpler than the alternatives. But that's the only time I've been tempted. I find structured objects far easier and safer to manipulate than strings. But if you don't need a full-on language, one easy step is to wrap your haskell functions in a typechecker: apply1 f [x] = f x apply1 _ _ = throw hissy fit apply2 f [x, y] = f x y etc. I would hope that the types could be checked statically, as I explained above. Now you can put them all into one container. Yes, the family of apply functions may be a little tedious, and you may be able to use typeclass magic to automatically select the right apply function, but it doesn't seem like a big deal to me. If you want to extend this to different types, you just have to extend this in one more direction, and a typeclass definitely helps there. Except that I now lose the ability to stick them all into the same container. (Unless I enable existential quantification.) -- Now, I can't see any obvious reason why I can't just keep adding -- new constructors to Question, and corresponding patterns to ask, -- answer and check, but I'm a lazy bugger and want to palm this off -- onto the users by telling them that I am empowering them by giving -- them the ability to add new question types to the framework. -- How would I enable them to do this without them having to mess with -- the original source? Well, I guess you could find the bits of the question framework which are always the same regardless of how its extended, then think about what types those have. Then export that as a library so your users can put together their own program based on that. For example, if you always have a number of wrong answers and a number of right answers and print a scoreboard, then you have 'Int - Int - Scoreboard'. If the answers the users are expected to give vary (a single int, or a list of ints, or a string), then you can export some parsing primitives. I'm pretty sure that you could never come up with a sufficiently large set of
Re: [Haskell-cafe] Client-extensible heterogeneous types (Duck-typed variadic functions?)
BTW Thanks: This discussion has helped me gain a better understanding of some of the mechanisms at work, which I really appreciate. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Client-extensible heterogeneous types
Greetings, I'm looking for dynamic dispatch on extensible sets of types. Here is a more detailed explanation of what I mean: # Consider the following Python code as representative of something # you might see in Object-Orineted programs in all sorts of languages. # Create an abstract type from abc import ABCMeta, abstractmethod class Abstract: __metaclass__ = ABCMeta @abstractmethod def method(self): pass # Provide some reifications of the abstract type class Variant1(Abstract): def method(self): return Variant 1 stuff class Variant2(Abstract): def method(self): return Variant 2 stuff # Provide some utilities to process these data def heterogeneousProcessor(data): return [datum.method() for datum in data] # If you wrap all the above up in a library, clients can easily extend # it with their own new types which will still work within the # framework class ClientDefined(Abstract): def method(self): return Client-defined stuff heterogeneousContainer = [Variant1(), Variant2(), ClientDefined()] result = heterogeneousProcessor(heterogeneousContainer) -- In Haskell, on the one hand, the heterogeneity is easily provided -- by algebraic data types data AbstractHeterogeneous = VariantHeterogeneous1 | VariantHeterogeneous2 methodHeterogeneous VariantHeterogeneous1 = Variant 1 stuff methodHeterogeneous VariantHeterogeneous2 = Variant 2 stuff heterogeneousProcessor dataa = [methodHeterogeneous datum | datum - dataa] heterogeneousContainer = [VariantHeterogeneous1, VariantHeterogeneous2] resultHeterogeneous = heterogeneousProcessor heterogeneousContainer -- But in order to extend the set of variants, the client would have -- to modify the source code, changing the definiton of -- AbstractHeterogeneous and methodHeterogeneous, both of which belong -- to the library. -- On the other hand, the extensibility is easily provided by type -- classes -- Library code: class AbstractExtensible a where methodExtensible :: a - String instance AbstractExtensible () where methodExtensible _ = Variant 1 stuff instance AbstractExtensible Char where methodExtensible _ = Variant 2 stuff -- Client extension: instance AbstractExtensible Int where methodExtensible _ = Client-defined stuff -- but in this case, there is no heterogeneity: you cannot create the -- equivalent of heterogeneousContainer above -- heterogeneousExtensibleContainer = resultExtensible :: [String] resultExtensible = [methodExtensible (), methodExtensible 'a', methodExtensible (1::Int)] I can't see a Haskell solution which combines both of these orthogonal features without losing the benefits of the type system. (For example, I could create my own, weak, type system with tags to identify the type and maps to do the dispatch.) So my question is, what would be the Haskell approach to combining heterogeneity (as provided by variant (algebraic) types) with type-extensibility (as provided by type classes), without losing the benefits of Haskell's type system? I haven't looked into Template Haskell, but i guess that it is likely to provide a solution. But is there a solution in plain Haskell? Thanks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Client-extensible heterogeneous types
[Sorry Stephen, didn't mean to take this off-list, hence the resend.] On 2010 Oct 12, at 14:31, Stephen Tetley wrote: To do this I would use dynamic types (via Data.Dynamic). Ah, yes, I've just stumbled upon these while trying to figure out what APPLY or FUNCALL would mean in Haskell. There are more typeful ways to deal with heterogeneous structures[*], but if clients can easily extend it with their own new types you've pretty much defined what dynamic types solve. Cool. I've just started experimenting with implementing the dynamism by holding functions (methods) alongside data in a variant type. I think I'll see what I learn by taking this a bit further, before digging into Data.Dynamic, but it's good to know there is some prior art to turn to in the long run. Many thanks. Reading the GHC docs on Data.Dynamic, I infer that Data.Dynamic is non- standard, but, in principle, portable to other implementations. Is that understanding correct? [*] See the HList papers and library and various solutions to the expression problem. This seems to be extremely relevant too, though I think that I'll stick to my own experiment and Data.Dynamic to start with. Thanks very much. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe