
Hi Konrad,
I am a Haskell newbie working on my first serious test case, and I would like some feedback from the experts to make sure I am not doing anything stupid ;-)
Well, I may not exactly qualify, but I can give you a few suggestions, nonetheless...
data Floating a => Vector a = Vector !a !a !a deriving (Eq, Show)
Here. Do not use 'data C x =>'. It's essentially a useless part of the language that really should have gone away. What you want is just: | data Vector a = Vector !a !a !a deriving (Eq, Show) The Floating constraint can come in on the functions. (I say this feature is useless because it only does one thing: disallows you to construct Vectors whose elements aren't instances of Floating. However, the useful thing that it might do -- namely, allow you to *use* the fact that the elements are instances of Floating -- it doesn't.)
I would like to keep the numerical representation as general as possible, in particular to postpone decisions about precision (Float, Double, eventually arbitrary precision arithmetic) as much as possible. Therefore the "Floating a" constraint. Which leads to my first question: doing it the way I did, I find myself having to add a "Floating a" constraint to almost every function specification with a vector argument. I would prefer to specify once and for all that vector elements need to be "Floating", everywhere. Is there a way of doing that?
Not really.
-- Periodic universe data Floating a => OrthorhombicUniverse a = OrthorhombicUniverse a a a
Again, get rid of the 'Floating a =>' part.
instance Floating a => Universe (OrthorhombicUniverse a) where distanceVector (OrthorhombicUniverse a b c) (Vector x1 y1 z1) (Vector x2 y2 z2) = Vector (fmod (x2-x1) a) (fmod (y2-y1) b) (fmod (z2-z1) c) where fmod x y = x - y*truncate (x/y)
There are actually two problems. First, you want to write fmod as: | fmod x y = x - y * fromInteger (truncate (x/y)) otherwise the type is wrong. Secondly, since you're using truncate, you need to be in RealFrac, not in Floating. Changing the signature to: | instance RealFrac a => ... fixes this problem. However, once we fix this, we can see the real problem. Your Universe class has a method, distanceVector, of type: | distanceVector :: Universe u, Floating a => u -> Vector a -> Vector a -> Vector a And here's the problem. When 'u' is 'OrthorhombicUniverse x', it doesn't know that this 'x' is supposed to be the same as the 'a'. One way to fix this is to parameterize the Universe data type on the element, something like: class Universe u where distanceVector :: (RealFrac a, Floating a) => u a -> (Vector a) -> (Vector a) -> (Vector a) distance :: (RealFrac a, Floating a) => u a -> (Vector a) -> (Vector a) -> a distance u v1 v2 = norm (distanceVector u v1 v2) -- Infinite universe data InfiniteUniverse a = InfiniteUniverse instance Universe InfiniteUniverse where distanceVector u v1 v2 = v2 <-> v1 -- Periodic universe data OrthorhombicUniverse a = OrthorhombicUniverse a a a instance Universe OrthorhombicUniverse where distanceVector (OrthorhombicUniverse a b c) (Vector x1 y1 z1) (Vector x2 y2 z2) = Vector (fmod (x2-x1) a) (fmod (y2-y1) b) (fmod (z2-z1) c) where fmod x y = x - y*fromInteger (truncate (x/y)) This is beginning to get a little ugly, but I think that's largely because you're using type classes in too much of an OO style (this is what a lot of my first programs looked like and I think for reasons similar to this, I moved away from that). However, not knowing more about the domain of discourse, I don't know what to suggest. Perhaps using the module system would serve you better. Instead of having a universe class, simply put each universe in a separate module and provide the same functions in each. Then you just import them selectively, or qualified. HTH. - Hal

On Fri, Jul 25, 2003 at 08:31:26AM -0700, Hal Daume wrote:
However, once we fix this, we can see the real problem. Your Universe class has a method, distanceVector, of type:
| distanceVector :: Universe u, Floating a => u -> Vector a -> Vector a -> Vector a
And here's the problem. When 'u' is 'OrthorhombicUniverse x', it doesn't know that this 'x' is supposed to be the same as the 'a'. One way to fix this is to parameterize the Universe data type on the element, something like:
class Universe u where distanceVector :: (RealFrac a, Floating a) => u a -> (Vector a) -> (Vector a) -> (Vector a) ...
Another approach is to make Universe a multi-parameter type class: class (RealFrac a, Floating a) => Universe u a | u -> a where distanceVector :: u -> Vector a -> Vector a -> Vector a ... You need to use ghc with '-fglasgow-exts' for this. Peace, Dylan

On Friday, 2003-07-25, 21:48, Dylan Thurston wrote:
[...]
Another approach is to make Universe a multi-parameter type class:
class (RealFrac a, Floating a) => Universe u a | u -> a where distanceVector :: u -> Vector a -> Vector a -> Vector a ...
You need to use ghc with '-fglasgow-exts' for this.
Or hugs with '-98'.
Peace, Dylan
Wolfgang

Hi all, I have a question on compiling a concurrent haskell source code using GHC. Today is my first time playing around with concurrency in Haskell, and this afternoon, GHC seemed to be able to compile my code and produced an executable. However, that executable did not seem to run the program correctly. In fact, it just did not do anything. FYI, GHCi interpreted the code succesfully, and the program runs normally under GHCi. I compiled the code this way: ghc --make source.hs -o output Do I need to have a specific flag or something? I tried to look at GHC's documentation, but I just could not find any information on this except adding -syslib concurrent flag, which also did not help. Thank you very much for the help. Blessings, Dennis Sidharta --------------------------------- Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software

Hi all,
I have a question on compiling a concurrent haskell source code using GHC. Today is my first time playing around with concurrency in Haskell, and this afternoon, GHC seemed to be able to compile my code and produced an executable. However, that executable did not seem to run the program correctly. In fact, it just did not do anything. FYI, GHCi interpreted the code succesfully, and the program runs normally under GHCi.
I compiled the code this way: ghc --make source.hs -o output
Please post the code, a description of what it did, and what you expected it to do. If the code is too large for an email, put it on your web server and point us at it, or cut it down to a smaller version that still exhibits the problem, and include that. We can't help you if we don't have this information. --KW 8-)

Hi Keith,
With this email I attached the source code. As you can see, it is very simple. And in case you would like to know, I wrote that program for a short tutorial on Haskell for a programming language course I took last semester.
Thank you very much.
Blessings,
Dennis
Keith Wansbrough
Hi all,
I have a question on compiling a concurrent haskell source code using GHC. Today is my first time playing around with concurrency in Haskell, and this afternoon, GHC seemed to be able to compile my code and produced an executable. However, that executable did not seem to run the program correctly. In fact, it just did not do anything. FYI, GHCi interpreted the code succesfully, and the program runs normally under GHCi.
I compiled the code this way: ghc --make source.hs -o output
Please post the code, a description of what it did, and what you expected it to do. If the code is too large for an email, put it on your web server and point us at it, or cut it down to a smaller version that still exhibits the problem, and include that. We can't help you if we don't have this information. --KW 8-) _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe --------------------------------- Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software

Dennis Sidharta wrote:
[ problems with concurrent Haskell ]
I can see two problems in your code: * forkIO creates "daemon threads", so the program terminates immediately. * Chan is an unbounded channel, so you won't get a "ping pong", which is probably what you expected. MVar is your friend here. See http://haskell.org/ghc/docs/latest/html/base/Control.Concurrent.html Cheers, S.

Hi Sven,
Thanks for the pointer! I will try to play around with MVar.
Sincerely,
Dennis
Sven Panne
[ problems with concurrent Haskell ]
I can see two problems in your code: * forkIO creates "daemon threads", so the program terminates immediately. * Chan is an unbounded channel, so you won't get a "ping pong", which is probably what you expected. MVar is your friend here. See http://haskell.org/ghc/docs/latest/html/base/Control.Concurrent.html Cheers, S. --------------------------------- Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software

Hi again,
I have tried to play around with MVar today, but
still... I did not see how to synchronize MVar without
the help of forkIO, and then explicitly call yield ::
IO (). But then, if I use forkIO I will create "daemon
threads" that will cause my program to terminates
immediately (back to the original problem).
I attached the source code to this email.
ps: If you can tell the depth of my understanding of
concurrent Haskell from my code, please do not
hesitate to evaluate it (Eg. am I using MVar
correctly? Any better method? etc.), since I am really
new to concurrent Haskell. Thanks.
Again, thank you for the help.
Sincerely,
Dennis Sidharta
--- Sven Panne
Dennis Sidharta wrote:
[ problems with concurrent Haskell ]
I can see two problems in your code:
* forkIO creates "daemon threads", so the program terminates immediately.
* Chan is an unbounded channel, so you won't get a "ping pong", which is probably what you expected. MVar is your friend here.
See
http://haskell.org/ghc/docs/latest/html/base/Control.Concurrent.html
Cheers, S.
__________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com

On Wed, 30 Jul 2003, Dennis Sidharta wrote:
Hi again,
I have tried to play around with MVar today, but still... I did not see how to synchronize MVar without the help of forkIO, and then explicitly call yield :: IO (). But then, if I use forkIO I will create "daemon threads" that will cause my program to terminates immediately (back to the original problem).
The Haskell program terminates when the main thread is done. Your main thread is done as soon as it forks the two other threads. If you want to be sure your additional threads get to run, you must have the main thread wait for them to finish (using one or more MVars, of course). See the section "Terminating the program" in the documentation for the Control.Concurrent module.
I attached the source code to this email.
ps: If you can tell the depth of my understanding of concurrent Haskell from my code, please do not hesitate to evaluate it (Eg. am I using MVar correctly? Any better method? etc.), since I am really new to concurrent Haskell. Thanks.
If you want your two additional threads to have a proper dialogue, you need *two* MVars. (This is not a Haskell issue but a concurrency issue.) Having fixed that, you'll find that you don't need (or want) the `yield`s. Your code has lots of repeated patterns. Time to abstract a bit more!
Again, thank you for the help.
Sincerely,
Dennis Sidharta
--- Sven Panne
wrote: Dennis Sidharta wrote:
[ problems with concurrent Haskell ]
I can see two problems in your code:
* forkIO creates "daemon threads", so the program terminates immediately.
* Chan is an unbounded channel, so you won't get a "ping pong", which is probably what you expected. MVar is your friend here.
See
http://haskell.org/ghc/docs/latest/html/base/Control.Concurrent.html
Cheers, S.
Dean

G'day all. On Fri, Jul 25, 2003 at 03:48:15PM -0400, Dylan Thurston wrote:
Another approach is to make Universe a multi-parameter type class:
class (RealFrac a, Floating a) => Universe u a | u -> a where distanceVector :: u -> Vector a -> Vector a -> Vector a ...
Actually, this is a nice way to represent vector spaces, too: class (Num v, Fractional f) => VectorSpace vs v f | vs -> v f where scale :: vs -> f -> v -> v innerProduct :: vs -> v -> v -> f The reason why you may want to do this is that you may in general want different inner products on the same vectors, which result in different vector spaces. Cheers, Andrew Bromage

On Mon, Jul 28, 2003 at 11:59:48AM +1000, Andrew J Bromage wrote:
G'day all.
On Fri, Jul 25, 2003 at 03:48:15PM -0400, Dylan Thurston wrote:
Another approach is to make Universe a multi-parameter type class:
class (RealFrac a, Floating a) => Universe u a | u -> a where distanceVector :: u -> Vector a -> Vector a -> Vector a ...
Actually, this is a nice way to represent vector spaces, too:
class (Num v, Fractional f) => VectorSpace vs v f | vs -> v f where scale :: vs -> f -> v -> v innerProduct :: vs -> v -> v -> f
The reason why you may want to do this is that you may in general want different inner products on the same vectors, which result in different vector spaces.
Hmm, that's an interesting technique, which I'll have to try out; there are several instances where you want different versions of the same structure on some elements. This is an interesting alternative to newtype wrapping or some such. However, I would be sure to distinguish between an inner product space and a vector space. A vector space has only the 'scale' operation above (beyond the +, -, and 0 from Num); you will rarely want to have different versions of the scale operation for a given set of vectors and base field. An inner product space has the 'innerProduct' operation you mention; as you say, there is very frequently more than one interesting inner product. Peace, Dylan

G'day all. On Sun, Jul 27, 2003 at 10:36:46PM -0400, Dylan Thurston wrote:
However, I would be sure to distinguish between an inner product space and a vector space.
That's true. If you're after a completely generic solution, this might be an issue.
An inner product space has the 'innerProduct' operation you mention; as you say, there is very frequently more than one interesting inner product.
I might also add that normalisation doesn't necessarily make sense on every inner product space. In my situation, for example, the scalar field is Rational, so it wasn't closed under square root. Cheers, Andrew Bromage

On Mon, Jul 28, 2003 at 03:23:30PM +1000, Andrew J Bromage wrote:
G'day all.
On Sun, Jul 27, 2003 at 10:36:46PM -0400, Dylan Thurston wrote:
However, I would be sure to distinguish between an inner product space and a vector space.
That's true. If you're after a completely generic solution, this might be an issue.
Err, but you yourself raised exactly the reason why you want to make this distinction (and put inner products in their own class): you sometimes want different inner products on the same set of vectors. Peace, Dylan

On Friday 25 July 2003 21:48, Dylan Thurston wrote:
Another approach is to make Universe a multi-parameter type class:
class (RealFrac a, Floating a) => Universe u a | u -> a where distanceVector :: u -> Vector a -> Vector a -> Vector a ...
You need to use ghc with '-fglasgow-exts' for this.
What is the general attitude in the Haskell community towards compiler-specific extensions? My past experience with Fortran and C/C++ tells me to stay away from them. Portability is an important criterion for me. Konrad.

On Mon, 28 Jul 2003, Konrad Hinsen wrote:
What is the general attitude in the Haskell community towards compiler-specific extensions? My past experience with Fortran and C/C++ tells me to stay away from them. Portability is an important criterion for me.
It depends which ones. Some are implemented in multiple compilers in a consistent way and widely liked and used, and are rather likely to make it into the next standard version of Haskell in much their current form. (For instance, portability is an important criterion for us, too, but we still use multi-parameter typeclasses.) Others are still sufficiently experimental that ideas really are just being played with. It would be interesting to see a list of what people think will make it into Haskell 2 though. -- Mark

On Mon, 28 Jul 2003 09:54:11 -0400 (EDT) Mark Carroll wrote: It would be
interesting to see a list of what people think will make it into Haskell 2 though.

On Mon, Jul 28, 2003 at 03:42:11PM +0200, Konrad Hinsen wrote:
On Friday 25 July 2003 21:48, Dylan Thurston wrote:
Another approach is to make Universe a multi-parameter type class:
class (RealFrac a, Floating a) => Universe u a | u -> a where distanceVector :: u -> Vector a -> Vector a -> Vector a ...
You need to use ghc with '-fglasgow-exts' for this.
What is the general attitude in the Haskell community towards compiler-specific extensions? My past experience with Fortran and C/C++ tells me to stay away from them. Portability is an important criterion for me.
I think it depends on the extension. I find multi-parameter type classes genuinely very useful, and the functional dependencies notation (the '| u -> a' above) has been around for a while and seems to be becoming standard. Hugs, for instance, implements these same extensions, and it seems very likely to me to be part of the next Haskell standard. On the other hand, some ghc extensions, like generic Haskell, seem much more preliminary to me; if you want portable code, I would stay away from them. There was some discussion earlier about formalising some of these extensions. As far as I know, the FFI is the only one for which this has been completed; but I think multi-parameter type classes would be a natural next choice. Peace, Dylan

G'day all. On Mon, Jul 28, 2003 at 03:42:11PM +0200, Konrad Hinsen wrote:
What is the general attitude in the Haskell community towards compiler-specific extensions? My past experience with Fortran and C/C++ tells me to stay away from them. Portability is an important criterion for me.
There is no ISO standard Haskell. There is Haskell 98, but that was deliberately designed to be a simpler language than what came before it, with no experimental features, partly to make teaching the language easier. (You can't write a textbook for a moving target.) The situation with Haskell today is somewhat analogous to C++ _during_ its standardisation process, when people were proposing all kinds of proposed language features (exceptions spring to mind as one example) which not everyone supported and some supported incompletely. As others have noted, using features which are almost certainly going to end up in the next "official" standard is a pretty safe bet, because your code will work everywhere eventually. Cheers, Andrew Bromage

On Tuesday 29 July 2003 04:10, Andrew J Bromage wrote:
There is no ISO standard Haskell. There is Haskell 98, but that was deliberately designed to be a simpler language than what came before it, with no experimental features, partly to make teaching the language easier. (You can't write a textbook for a moving target.)
True. However, for those who, like me, haven't yet seen much beyond textbooks, the textbook standard is the reference. It is not so easy to figure out which extensions are experimental or satisfy a few persons' taste and which are likely to stay.
The situation with Haskell today is somewhat analogous to C++ _during_ its standardisation process, when people were proposing all kinds of
I think that C++ was a lot worse, even the accepted features (e.g. templates) didn't work the same with all compilers. All non-trivial code came with a list of supported compilers. Konrad. -- ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsen@cnrs-orleans.fr Centre de Biophysique Moleculaire (CNRS) | Tel.: +33-2.38.25.56.24 Rue Charles Sadron | Fax: +33-2.38.63.15.17 45071 Orleans Cedex 2 | Deutsch/Esperanto/English/ France | Nederlands/Francais -------------------------------------------------------------------------------

G'day all. On Tue, Jul 29, 2003 at 12:11:29PM +0200, Konrad Hinsen wrote:
I think that C++ was a lot worse, even the accepted features (e.g. templates) didn't work the same with all compilers. All non-trivial code came with a list of supported compilers.
True. If we had more Haskell implementations, we might be in the same boat. Our situation is much simpler. Code is either written for Haskell 98, or for "Glasgow extensions". Cheers, Andrew Bromage

On Wed, Jul 30, 2003 at 02:04:22PM +1000, Andrew J Bromage wrote:
On Tue, Jul 29, 2003 at 12:11:29PM +0200, Konrad Hinsen wrote:
I think that C++ was a lot worse, even the accepted features (e.g. templates) didn't work the same with all compilers. All non-trivial code came with a list of supported compilers.
True. If we had more Haskell implementations, we might be in the same boat.
Our situation is much simpler. Code is either written for Haskell 98, or for "Glasgow extensions".
Almost. There's Haskell 98, H98 plus common extensions (the baseline for the hierarchical libraries), a larger language accepted by both GHC and Hugs, and then there's GHC.

Well, I may not exactly qualify, but I can give you a few suggestions, nonetheless...
Thanks!
data Floating a => Vector a = Vector !a !a !a deriving (Eq, Show)
Here. Do not use 'data C x =>'. It's essentially a useless part of the language that really should have gone away. What you want is just: | data Vector a = Vector !a !a !a deriving (Eq, Show)
The Floating constraint can come in on the functions.
(I say this feature is useless because it only does one thing: disallows you to construct Vectors whose elements aren't instances of Floating. However, the useful thing that it might do -- namely, allow you to *use* the fact that the elements are instances of Floating -- it doesn't.)
That was indeed what I expected it would do. Is there any reason why it doesn't, other than historical accident? It looks like a useful feature to me.
There are actually two problems. First, you want to write fmod as: | fmod x y = x - y * fromInteger (truncate (x/y))
OK, that's obvious.
otherwise the type is wrong. Secondly, since you're using truncate, you
need to be in RealFrac, not in Floating. Changing the signature to: | instance RealFrac a => ...
fixes this problem.
OK, that looks reasonable too (but the multitude of number classes does not yet look reasonable to me - I'll have to print a description and put it next to my keyboard).
And here's the problem. When 'u' is 'OrthorhombicUniverse x', it doesn't know that this 'x' is supposed to be the same as the 'a'. One
Indeed...
way to fix this is to parameterize the Universe data type on the element, something like:
OK, that works. But it doesn't make my code any nice, it means many more type constraints all over the code.
This is beginning to get a little ugly, but I think that's largely because you're using type classes in too much of an OO style (this is
I am coming from OO indeed...
similar to this, I moved away from that). However, not knowing more about the domain of discourse, I don't know what to suggest. Perhaps using the module system would serve you better. Instead of having a universe class, simply put each universe in a separate module and provide the same functions in each. Then you just import them selectively, or qualified.
I don't think this would be appropriate to me. I want to be able to use multiple universe types in the same program, but qualified imports are not a solution either, as there will be a lot of code referring to generic universes. More fundamentally, I consider the module system in its present form a major weak point of Haskell. There is only one global module namespace, which therefore is a scarce resource. If, as I have seen proposed in some book, I use up a global module name for each abstract data type, then I can almost expect to get name clashes as soon as I try to use my code together with someone else's (who thought that "vector" would be a great name for something slightly different). I have seen the proposal for hierarchical libraries, but that seems to be no more than a proposal at the moment. My intention is to write rather low-level library-style code for a specific yet wide application domain (scientific computing), which explains the need for generality. I haven't seen this issue addressed in any of the Haskell books or Web sites I know, so I would appreciate any pointers. It's a difficult problem for many languages, in fact I suspect that it's the main reason why languages like Fortran or C++ never got to the point of having sufficiently general libraries (I stopped counting the C++ matrix libraries, for example). Konrad.

Konrad Hinsen
More fundamentally, I consider the module system in its present form a major weak point of Haskell. There is only one global module namespace, which therefore is a scarce resource. If, as I have seen proposed in some book, I use up a global module name for each abstract data type, then I can almost expect to get name clashes as soon as I try to use my code together with someone else's (who thought that "vector" would be a great name for something slightly different). I have seen the proposal for hierarchical libraries, but that seems to be no more than a proposal at the moment.
The proposal for a hierarchical module *namespace* is much more than a proposal now. It is actively supported by all the current Haskell systems, and there is a large and growing collection of libraries that use it, many of them distributed with the compilers. Regards, Malcolm

At 15:40 28/07/03 +0200, Konrad Hinsen wrote:
This is beginning to get a little ugly, but I think that's largely because you're using type classes in too much of an OO style (this is
I am coming from OO indeed...
Me too. Twice now I have used Haskell classes in a way suggested by an OO programming background, and have later ended up replacing the class by a 'data' containing functions. Here's a point to consider: suppose you want to have a list of "class" instances: if you use the "class" mechanism, then every member of the list must be a member of the same instance type of the class, which is not what is usually required for OO programming. An alternative is to define something like:
data MyInterface = MyInterface { method1 :: Int -> String -> Blob , method2 :: Bool -> String -> Blob , method3 :: Blob -> String }
then if you have:
anObj :: MyInterface
and write functions like
foo = method1 anObj 5 "hello" bar = method3 anObj foo
etc.
In creating instances of MyInterface, the higher order function features of
Haskell, and currying, are most useful. Functions that return values of
type MyInterface take on the role of OO class constructors (or kit classes).
(The above code completely unchecked, but I hope it illustrates an approach.)
#g
-------------------
Graham Klyne
participants (15)
-
Andrew J Bromage
-
Dean Herington
-
Dennis Sidharta
-
Derek Elkins
-
dpt@exoskeleton.math.harvard.edu
-
dpt@math.harvard.edu
-
Graham Klyne
-
Hal Daume
-
Keith Wansbrough
-
Konrad Hinsen
-
Malcolm Wallace
-
Mark Carroll
-
Ross Paterson
-
Sven Panne
-
Wolfgang Jeltsch