[Haskell-cafe] Input and output of mathematical expressions

2011-06-09 Thread Jacek Generowicz

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

2011-06-09 Thread Jacek Generowicz


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)

2011-05-26 Thread Jacek Generowicz

[ 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)

2011-05-26 Thread Jacek Generowicz


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)

2011-05-26 Thread Jacek Generowicz


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)

2011-05-26 Thread Jacek Generowicz


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)

2011-05-26 Thread Jacek Generowicz


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

2011-05-25 Thread Jacek Generowicz


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

2011-05-25 Thread Jacek Generowicz

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

2011-05-25 Thread Jacek Generowicz


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

2011-05-25 Thread Jacek Generowicz


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

2011-05-25 Thread Jacek Generowicz


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

2011-05-25 Thread Jacek Generowicz


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

2011-05-25 Thread Jacek Generowicz


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

2011-05-25 Thread Jacek Generowicz


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

2011-05-24 Thread Jacek Generowicz


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

2011-05-24 Thread Jacek Generowicz

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

2011-05-24 Thread Jacek Generowicz


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

2011-05-24 Thread Jacek Generowicz


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*

2011-05-24 Thread Jacek Generowicz


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

2011-05-24 Thread Jacek Generowicz

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

2011-05-24 Thread Jacek Generowicz


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

2011-05-24 Thread Jacek Generowicz

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

2011-05-24 Thread Jacek Generowicz


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

2011-05-24 Thread Jacek Generowicz


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

2011-05-24 Thread Jacek Generowicz
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

2011-05-24 Thread Jacek Generowicz


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

2011-05-24 Thread Jacek Generowicz
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

2011-05-23 Thread Jacek Generowicz

[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

2011-05-23 Thread Jacek Generowicz


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

2011-05-23 Thread Jacek Generowicz


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

2011-05-23 Thread Jacek Generowicz


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

2011-05-23 Thread Jacek Generowicz


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

2011-05-23 Thread Jacek Generowicz


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

2011-05-23 Thread Jacek Generowicz


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

2011-05-23 Thread Jacek Generowicz
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

2011-05-23 Thread Jacek Generowicz
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

2011-05-23 Thread Jacek Generowicz


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?

2011-03-03 Thread Jacek Generowicz

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?

2011-03-03 Thread Jacek Generowicz

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?

2011-03-03 Thread Jacek Generowicz


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

2010-12-19 Thread Jacek Generowicz


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)

2010-12-17 Thread Jacek Generowicz

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

2010-12-17 Thread Jacek Generowicz

# 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

2010-12-13 Thread Jacek Generowicz

-- 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

2010-12-06 Thread Jacek Generowicz

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

2010-12-06 Thread Jacek Generowicz

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

2010-12-06 Thread Jacek Generowicz


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

2010-12-06 Thread Jacek Generowicz


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

2010-12-06 Thread Jacek Generowicz


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

2010-11-01 Thread Jacek Generowicz
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

2010-10-16 Thread Jacek Generowicz
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

2010-10-15 Thread Jacek Generowicz

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

2010-10-15 Thread Jacek Generowicz


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?)

2010-10-15 Thread Jacek Generowicz
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?)

2010-10-15 Thread Jacek Generowicz


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

2010-10-15 Thread Jacek Generowicz


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

2010-10-15 Thread Jacek Generowicz

-- 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

2010-10-15 Thread Jacek Generowicz

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

2010-10-15 Thread Jacek Generowicz


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

2010-10-15 Thread 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




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

2010-10-15 Thread Jacek Generowicz


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?)

2010-10-14 Thread Jacek Generowicz


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?)

2010-10-14 Thread Jacek Generowicz


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?)

2010-10-14 Thread Jacek Generowicz


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

2010-10-14 Thread Jacek Generowicz

[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?)

2010-10-14 Thread Jacek Generowicz


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?)

2010-10-14 Thread Jacek Generowicz


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?)

2010-10-14 Thread Jacek Generowicz


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?)

2010-10-14 Thread Jacek Generowicz


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?)

2010-10-14 Thread Jacek Generowicz

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

2010-10-13 Thread Jacek Generowicz


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?)

2010-10-13 Thread Jacek Generowicz


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

2010-10-13 Thread Jacek Generowicz


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?)

2010-10-13 Thread Jacek Generowicz


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?)

2010-10-13 Thread Jacek Generowicz
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

2010-10-12 Thread Jacek Generowicz

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

2010-10-12 Thread Jacek Generowicz

[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