Re: [Haskell-cafe] RE: Re[4]: [Haskell] Dynamic binding
Hello Ralf, Thursday, June 23, 2005, 11:40:13 PM, you wrote: RL a) building (i) a list of data is fundamentally different RL from building (ii) a list of anticipated results of each datum. RL I would be surprised to hear that this counts as a valid technique. RL BTW, you can do the *same* in a lazy OO language. (No lazy OO language RL at hand -- well lazyness can be simulated.) sorry, valid technique is technique that work :) i use in my own program all the three ways i mentioned to solve problems of different complexity afair, you are relatively new to Haskell (relatively to my 1-year experience :) and, i think, you are not share FP thinking style. when programming in Haskell, i think in terms what thing i will need in this point of program?. if i need, for example, a possibility to check string against regular expression, then i will pass a function which does this check, not original RE. if i need a possibility to draw a shape, i will pass action which draws this shape. if i need several functions, i just combine them in a tuple there is one interesting example in my program. i have a list of wildcards and list of filenames and for each filename i need to know number of first wildcard to which this filename matched. in early stages of my program development i just passed list of wildcards to file-finding routine (as [Wildcard]). then, i changed list of wildcards to list of functions which check match against each wildcard ([Filename-Bool]). and after that, i changed this to one function which just finds first True answer (Filename-Int). it was also more effective to compute this function only one time (it was something compiled on moment of computing and worked as fast as hand-written analyzer for given set of wildcards) as you see, i slowly migrated from traditional way of solving this problem to perfectly functional way and it was required several months RL a) building (i) a list of data is fundamentally different RL from building (ii) a list of anticipated results of each datum. i think that you don't have Haskell brain ;) and therefore don't trust functions, which are passed as parameters, collected in lists, saved in data structures and so on. you are prefer to put hands on some data, preferably an object, which can be manipulated with any method declared in his interface. i'm right? ;) FP encourage another way - passing functions which will then be applied to some additional arguments, as in my program, where file-finding function absolutely don't need list of wildcards. it just need to map filename to wildcard number, so a Filename-Int parameter is just enough in the draw example, each elment in a list was an action (having type IO() ), so i don't create list of anticipated results, i created list of actions which can be performed, for example, by sequence_ RL Anyway, even if people end up coding as you propose, RL it won't work in general. Think of mutation methods that RL change the state but preserve the type. Then your list will RL still be heterogonous. NO? my second example was just of this type. it uses IORefs to hold current state, but this IORefs don't need to appear in interface see method moveTo, which changes state variable center, and method draw, which uses this variable this state is just don't need to appear in interface definition :) circle x y r RL You are not talking about state but constructor arguments. interface definition is a structure ShapeInterface, which have only fields for exposed object methods. so it supports any figures in universe :) RL In OO, mutable state tends to leak to the interface, RL perhaps not as public fields, perhaps not even as public only in C++ and other languages which need to calculate object size :) declaration of _non-public_ fields in _interface_ is something strange ;) this state is just don't need to appear in interface definition :) if you need to maintain mutable state, this is also not a problem: data ShapeInterface = Shape { draw :: IO (), moveTo :: (Int,Int) - IO (), calcArea :: Float } circle x y r = do center - ref (x,y) return Shape { draw = val center = drawCircle r , moveTo = (center=:) , calcArea = pi*r*r } main = do figures - sequence [circle 1 2 3, square 4 5 6, circle 7 8 9] mapM_ draw figures mapM_ (moveTo (0,0)) figures mapM_ draw figures ref=newIORef val=readIORef (=:)=writeIORef -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] RE: Re[4]: [Haskell] Dynamic binding
I guess we just need to agree that we disagree. Of course, you are right that I am just a newbie when it comes to Haskell. How did you know that I am actually a Cobol programmer? Did you google? http://www.google.com/search?biw=1003hl=enq=Ralf+Cobol Seriously (?): 1. I never intended to impose any particular OO style on Haskeller's. Its more about the *intellectual* question whether we can take C++/C#/Java code and do a structure-preserving conversion to Haskell without starting to argue on paradigm conversion. Or as Alistair Bayley argues (Alistair, thanks for helping out!) http://www.haskell.org/tmrwiki/FpVsOo ... it might be that you need to interface with external OO code, or you are porting an existing program and need to remain faithful to the original design, if only because you don't understand it well enough to convert it to a functional design. ... Bulat, why not read all of this? Also see the end of that Wiki page, where a reference to a paper is given, which seems to solve all these problems, but my brain is to small to really be sure. ;-) 2. No matter how much you try, the code that you showed was not very close to a faithful Shapes implementation. If you dare to read the spec: http://onestepback.org/articles/poly/ http://www.angelfire.com/tx4/cus/shapes/ You made two proposals that don't solve the problem no matter of *style*: 1st proposal of Bulat: just create list of draw functions itself: [drawCircle (10,10) 5, drawSquare (20,20) 10] you are not expected that this problem can be solved with one line of code? :) My reply: you are not building a list of objects. You are not organizing a loop whose body iterates over a list and executes functionality. 2nd proposal of Bulat: for more complex tasks - declare interface as a structure: data ShapeInterface = Shape { draw :: IO (), moveTo :: Point - IO (), calcArea :: Float } and return this structures from constructor functions: circle x y r = Shape { draw = drawCircle center r, moveTo newCenter = , calcArea = pi*r*r } where center = Point x y square x y size = Shape { draw = , moveTo newCenter = , calcArea = size*szie } figures = [circle 1 2 3, square 4 5 6, circle 7 8 9] The tragedy here is that this stops to work once circles and squares do have different interfaces. You solution does not scale. Subtyping allows for interface extension, and the actual benchmark exploits this, but your code avoids it. Anyway the solution is trivial: ex. quantification, you didn't propose that. Cheers, Ralf (back to Cobol) -Original Message- From: Bulat Ziganshin [mailto:[EMAIL PROTECTED] Sent: Thursday, June 23, 2005 11:37 PM To: Ralf Lammel Cc: Pal-Kristian Engstad; haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] RE: Re[4]: [Haskell] Dynamic binding Hello Ralf, Thursday, June 23, 2005, 11:40:13 PM, you wrote: RL a) building (i) a list of data is fundamentally different RL from building (ii) a list of anticipated results of each datum. RL I would be surprised to hear that this counts as a valid technique. RL BTW, you can do the *same* in a lazy OO language. (No lazy OO language RL at hand -- well lazyness can be simulated.) sorry, valid technique is technique that work :) i use in my own program all the three ways i mentioned to solve problems of different complexity afair, you are relatively new to Haskell (relatively to my 1-year experience :) and, i think, you are not share FP thinking style. when programming in Haskell, i think in terms what thing i will need in this point of program?. if i need, for example, a possibility to check string against regular expression, then i will pass a function which does this check, not original RE. if i need a possibility to draw a shape, i will pass action which draws this shape. if i need several functions, i just combine them in a tuple there is one interesting example in my program. i have a list of wildcards and list of filenames and for each filename i need to know number of first wildcard to which this filename matched. in early stages of my program development i just passed list of wildcards to file-finding routine (as [Wildcard]). then, i changed list of wildcards to list of functions which check match against each wildcard ([Filename-Bool]). and after that, i changed this to one function which just finds first True answer (Filename-Int). it was also more effective to compute this function only one time (it was something compiled on moment of computing and worked as fast as hand-written analyzer for given set of wildcards) as you see, i slowly migrated from traditional way of solving this problem to perfectly functional way and it was
Re: [Haskell-cafe] type inference and named fields
Tomasz Zielonka wrote: voidcast v@(VariantWithTwo{}) = v { field1 = Void , field2 = Void } voidcast v@(VariantWithOne{}) = v { field1 = Void } I would not expect that updating only field1 can change the type of v. But it can. Note that if you change the second field1 to field3 (both in datatype definition and voidcast function), the code will be accepted. The right thing is to construct a new value. In the report, section 3.15.3, Updates Using Field Labels, the translation is simply a pattern-match and (re-)construction. There is no requirement that input and output types are the same. It can be a nice feature actually, I've used it once or twice. Obviously this (magic) reconstruction does not work always (and not in the given case). Even consecutive updates (that could be recognized by the desugarer) don't work: voidcast [EMAIL PROTECTED] = v { field1 = Void} {field2 = Void } I think, the type checker of programatica requires that input and output type of updated values are the same (not only because comma-separated field updates are desugared to consecutive updates.) Christian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type inference and named fields
Lennart Augustsson [EMAIL PROTECTED] writes: A somewhat similar problem exists even without fields: foo :: Either a b - Either () b foo (Left _) = Left () foo x@(Right _) = x Your example is less surprising than mine with fields. The expression x on the rhs of the last clause has type Either a b This does not match the signature, which claims Either () b So it is fairly easy to explain why this is rejected. Even if we change the definition of the Either type to omit the Left constructor (and correspondingly omit the first clause of foo's definition), you still get an error. Whereas in the named field example, the rhs expression v {field1=Void} does indeed have the type Fields Void as declared in the signature. The expression explicitly converts all the relevant interior fields to Void. At least, that is how it could appear to a naive programmer like me :-) After all, if I change the definition of the type Fields to omit the constructor VariantWithTwo (and correspondingly omit the first clause of voidcast's definition), then suddenly and miraculously, the second clause passes the type checker. It is a bit weird that adding a new constructor to a datatype can cause existing code to fail to typecheck! Regards, Malcolm data Fields a = VariantWithTwo { field1 :: a , field2 :: a } | VariantWithOne { field1 :: a } data Void = Void voidcast :: Fields a - Fields Void voidcast v@(VariantWithTwo{}) = v { field1 = Void , field2 = Void } voidcast v@(VariantWithOne{}) = v { field1 = Void } ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type inference and named fields
Malcolm Wallace wrote: Whereas in the named field example, the rhs expression v {field1=Void} does indeed have the type Fields Void as declared in the signature. The expression explicitly converts all the relevant interior fields to Void. At least, that is how it could appear to a naive programmer like me :-) If v has a second field with the same type of field1, do you really expect that field2 is silently casted to the new type of field1? (This would be unsafe) Christian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell] Dynamic binding
Ralf Lammel wrote: Can you just tell how *you* would favor encoding the shapes example that was posed by poster? (It might just be that your code would be very close to Lennart's proposal?) There is no universal answer. The shape example obviously is just a toy example. As long as I have no idea what *concrete* problem the original poster is trying to solve, I cannot really tell which approach is preferable for his endeavour. It seems more appropriate to describe the options and their trade-offs. First of all, note that very often, you do not need a heterogeneous collection at all. Then plain polymorphism with type classes is more than enough, and more than OO provides in that situation. In many cases where you need some kind of heterogenicity (is that a word?), the standard datatype approach shown by Lennart is perfectly suitable - in fact, often much more suitable than the OO solution. You know about the expression problem, and the two dual notions of extensibility? OO supports one dimension, datatypes the other. It depends on the problem which one is more important. When you really need OO-style intensional kind of behaviour selection then first-class functions can bring you quite a long way, and often with much less amount of boilerplate than typical OO solutions. When the behaviour you have to encapsulate in heterogeneous collection becomes more complex - say, more then just one or two functions - first-class functions can be tedious. Existential types represent a more coarse-grained and structured variant of the first-class function approach. They combine the power of first-class functions with the convenience of type classes, very similar to class-based objects. In these cases, they are the most appropriate solution. Note again that with the latter two solutions, as with the OO approach, you do not have extensibility on the operations dimension. Cheers, - Andreas -- Andreas Rossberg, [EMAIL PROTECTED] Let's get rid of those possible thingies! -- TB ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type inference and named fields
Christian Maeder [EMAIL PROTECTED] writes: voidcast :: Fields a - Fields Void voidcast v@(VariantWithTwo{}) = v { field1 = Void , field2 = Void } voidcast v@(VariantWithOne{}) = v { field1 = Void } I would not expect that updating only field1 can change the type of v. The right thing is to construct a new value. This looks as follows with record syntax: voidcast VariantWithTwo{} = VariantWithTwo { field1 = Void , field2 = Void } voidcast VariantWithOne{} = VariantWithOne { field1 = Void } Ah, but the reason I want to use field update, rather than a new construction on the rhs, is that my type really has lots of other fields (not mentioned here), which are all of fixed definite types (not parametric). It is much nicer to be able to write v { field1 = Void } than VariantWithOne { field1 = Void , field2 = field2 v , field3 = field3 v , field4 = field4 v , field5 = field5 v ... } which has so much more scope for making a mistake, not to mention the extra maintainance work required if I ever add or delete a field from the type. Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type inference and named fields
Malcolm Wallace wrote: Ah, but the reason I want to use field update, rather than a new construction on the rhs, is that my type really has lots of other fields (not mentioned here), which are all of fixed definite types (not parametric). It is much nicer to be able to write v { field1 = Void } than VariantWithOne { field1 = Void , field2 = field2 v , field3 = field3 v , field4 = field4 v , field5 = field5 v ... } There is no problem with the desirable short version of updating if the type of v does not change! Only for a polymorphic record data type suitable map (or update) functions should be considered. Your long version is (of course) wrongly typed if the type of another field depends on the type of field1. Christian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: [Haskell] Dynamic binding
Hello Andrew, Friday, June 24, 2005, 12:35:16 AM, you wrote: AW Assuming I have a list of shapes somewhere in my program. The list would AW be heterogeneous, or at least contain data constructed using various AW different type constructors. The list would also be changing all the AW time, for example in a drawing program. So, using the suggestion of a AW list of drawing functions, would this not mean I would have to alter the AW list of drawing functions each time I alter the list of shapes? of course, we suggest this solution only for cases when all you need from shapes - to draw them. as i write in previous letter, one time i changed a list of regular expressions to list of functions that check matches with these regular expressions because it was the only operation i need if you require several operations, you can pack them in tuple or structure (really, tuple is a structure without field names) if you need fields/interfaces inheritance, then this method will not work. but in 90% of cases it's enough. in C++, creating classes is the most useful method of structuring program, so it is used for any problem - from very simple to most complex. when you translate such thing to Haskell, it's better to see which concrete problem are solved with help of classes, and not to emulate the classes itself (because in this case you will write many unneeded code) AW It does AW not seem an extensible solution. When it comes to adding new types or AW new functionality for existing types would it not be easy to miss AW updating a part of the program source that needed updating? adding new class needs adding one constructor function. it's hard to skip that part :) adding new function to interface need to change interface structure definition or adding new element to tuple. then type-checker of Haskell compiler will force you to add new function to all places where this structure/tuple are created. you just never worked with such strong type-checking as in Haskell AW The example I have found the simplest is the one given by Lennart, AW however this to me seems equivalent to the way people use switch AW statements in C to mimic dynamic binding. only because it's C-like :) you just can't believe that Haskell program can be 3-10 times smaller while keeping the same functionality :))) -- Best regards, Bulatmailto:[EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Re: [Haskell] Dynamic binding
Bulat wrote: if you require several operations, you can pack them in tuple or structure (really, tuple is a structure without field names) How are we going to anticipate all possible bodies of a for-loop? By comparison, when we build a normal Haskell list, does the construction precisely mirror what we are going to *do* with each element? Fold the map then!!! if you need fields/interfaces inheritance, then this method will not work. but in 90% of cases it's enough. What to do for the other 10%? in C++, creating classes is the most useful method of structuring program, so it is used for any problem - from very simple to most complex. when you translate such thing to Haskell, it's better to see which concrete problem are solved with help of classes, and not to emulate the classes itself (because in this case you will write many unneeded code) Yes, but we ought to solve the shapes problem. The shapes example is in Bulat's 10% region. only because it's C-like :) you just can't believe that Haskell program can be 3-10 times smaller while keeping the same functionality :))) But note that same functionality is one thing, having separate compilation and program extensibility too is another one. Ralf ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: [Haskell] Dynamic binding
Ralf Lammel wrote: only because it's C-like :) you just can't believe that Haskell program can be 3-10 times smaller while keeping the same functionality :))) But note that same functionality is one thing, having separate compilation and program extensibility too is another one. As I said, and as is well-known, extensibility is a red herring in this context - you merely trade one dimension of extensibility for another one. Cheers, - Andreas -- Andreas Rossberg, [EMAIL PROTECTED] Let's get rid of those possible thingies! -- TB ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Re: [Haskell] Dynamic binding
But note that same functionality is one thing, having separate compilation and program extensibility too is another one. As I said, and as is well-known, extensibility is a red herring in this context - you merely trade one dimension of extensibility for another one. I am not going to fight for extensibility. It's just that I believe that there is a value in a direct correspondence as opposed to a transcription. I cite from the OOHaskell abstract: The [...] code [...] demonstrates that OO code translates into OOHaskell in an intuition-preserving way: essentially expression-by-expression, without requiring global transformations. I would like to add a peer-reviewed clear reference to the OOHaskell paper about the red herring that you mention. I don't have such a reference. May I kindly ask you to offer a few for selection? Thanks, Ralf ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type inference and named fields
Malcolm Wallace wrote: Here is a strawman proposal, which does not fix the consecutive update problem, but which might address the original typing problem. I think it does not really address the original typing problem. It would allow you to write: voidcast v@(VariantWithTwo{}) = v { field1 = Void , field2 = Void } voidcast v@(VariantWithOne{}) = v { field1 = Void , field2 = Void } Setting field2 only assures type correctness, but the value of field2 would be ignored at runtime. I'ld rather define an empty polymorphic element and update that one: e = VariantWithOne { field1 = undefined } voidcast VariantWithOne{} = e { field1 = Void } In the last line e is (only) instantiated (and not casted). The Report (section 3.15) defines the following conditions on a named field update: * all labels must be taken from the same datatype * at least one constructor must define all of the labels mentioned in the update * no label may be mentioned more than once * an execution error occurs when the value being updated does not contain all of the specified labels. Now, this last condition is rather nasty - a runtime error - and I would like to eliminate it. I think we can do so by also eliminating the second condition. That is, I would like to be able to use a set of labels that might not be contained solely within a single constructor. The obvious semantics is that if a constructed value does not contain a label of that type, that part of the update is discarded. Hence, I could write a single expression that updated all possible variants of a type, simply by unioning all their possible labels. I want to detect errors as early as possible. Christian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: [Haskell] Dynamic binding
Ralf Lammel wrote: I would like to add a peer-reviewed clear reference to the OOHaskell paper about the red herring that you mention. I don't have such a reference. May I kindly ask you to offer a few for selection? Off-hand, I recall a paper by Martin Odersky and the Scala people discussing their approach to the Expression Problem, and a related paper by Jacques Garrigue, where he proposes to solve it using OCaml's polymorphic variants. Both should be easy to dig up with Google, and probably contain further pointers. Hope this helps, - Andreas -- Andreas Rossberg, [EMAIL PROTECTED] Let's get rid of those possible thingies! -- TB ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Re: [Haskell] Dynamic binding
Off-hand, I recall a paper by Martin Odersky and the Scala people discussing their approach to the Expression Problem, So ... http://icwww.epfl.ch/publications/documents/IC_TECH_REPORT_200433.pdf ... I guess The key innovative idea there is composition of mixins while replacing formal superclasses of mixins by the actual base class for mixin composition. I quote: In a mixin composition A with B with C, class A acts as actual superclass of mixins B and C, replacing the declared superclasses of B and C. To maintain type soundness, A must be a subclass of the declared superclasses of B and C. A super reference in either B or C will refer to a member of class A. As is the case for trait composition, Scala's mixin composition is commutative in the mixins - A with B with C is equivalent to A with C with B. In OOHaskell, you would parameterize in the superclass and that's it. DISCLAIMER: we haven't tried this. Thanks for the inspiration. and a related paper by Jacques Garrigue, where he proposes to solve it using OCaml's polymorphic variants. I am not sure. Is this referring to Objective Label? Which paper exactly? Hope this helps, It's interesting but I don't see how we make progress with the original (by now perhaps trivial) question regarding the transportation of an OO design into Haskell. The shapes problem doesn't call for Odersky's new contribution: I quote: We add to this list the following criterion: * Independent extensibility: It should be possible to combine independently developed extensions so that they can be used jointly [21]. The shapes problem rather calls for silly subtyping polymorphism. So we are beating a dead horse (or a red herring) by detouring to Scala unless I don't get you were hinting at. BTW, I just notice that Oderksy's list of partial solutions isn't complete: - Visitor combinators (Joost Visser) complementing Palsberg et al. - Many forms of generic functional programming (Hinze etc.) - Haskell type classes allow for extension in both type and processor extension. It's getting late here. Ralf ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type inference and named fields
Christian Maeder [EMAIL PROTECTED] writes: voidcast v@(VariantWithOne{}) = v { field1 = Void , field2 = Void } Setting field2 only assures type correctness, but the value of field2 would be ignored at runtime. Exactly what I was proposing. I could write a single expression that updated all possible variants of a type, simply by unioning all their possible labels. I want to detect errors as early as possible. But you can already write this: voidcast v@(VariantWithOne{}) = v { field1 = Void , field2 = Void } and you do not get a compile time error - it is a runtime error. I am proposing that it should not be thought of as an error at all. Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] type inference and named fields
Jonathan Cast wrote: No type theory (that I know of) goes beyond System F in accepting anything like foo. So, given the current state of the art, foo is unconditionally ill-typed. That could change if someone comes up with a /consistent/ type theory that accepts foo, but foo is ill-typed at the moment. As you say, we use types in programming languages because they help us, not because we want to implement type systems. So if a program makes sense when you ignore the types, it would be nice if the type system accepts it. My little program makes sense, but is not accepted by Haskell. Nor am I proposing that it should be accepted by Haskell. I was only giving an example of something that makes sense, but isn't allowed. There are, of course, type systems where my program works fine. O'Haskell is an example of a language with such a type system. In O'Haskell the Either type is defined like this: data Left a = Left a data Right a = Right a data Either a b Left a, Right b which means that Either is really a union of the Left and Right types. Now my program type checks. :) foo :: Either a b - Either () b foo (Left _) = Left () foo x@(Right _) = x And it has type checked in various type systems for quite a while, but not in System F. But System F is not the end all of type systems. -- Lennart ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Why I Love Haskell In One Simple Example
I posted this on my blog at http://changelog.complete.org/node/339 but I thought there may be some here that would find it of use. I recently implemented some new Haskell numeric types that, instead of performing calculations, can generate a rendering of the requested calculation or store units with it. Here you see a transcript of my session with a Haskell interpreter. The mathematical statements I am entering after the are standard Haskell expressions, and, as I demonstrate, normally evaluate to a single result. Once I get a more powerful simplifier, I will probably write a LaTeX exporting function as well. The entire implementation of this, BTW, is less than 200 lines. NumTest 5 + 1 * 3 8 NumTest prettyShow $ 5 + 1 * 3 5+(1*3) NumTest rpnShow $ 5 + 1 * 3 5 1 3 * + NumTest prettyShow $ 5 + 1 * 3 5+(1*3) NumTest prettyShow $ simplify $ 5 + 1 * 3 5+3 NumTest prettyShow $ 5 * (Symbol x) + 3 (5*x)+3 NumTest 5 / 2 2.5 NumTest (units 5 m) / (units 2 s) 2.5_m/s NumTest (units 5 m) / 2 2.5_m NumTest 10 * (units 5 m) / (units 2 s) 25.0_m/s NumTest sin (pi/2) 1.0 NumTest sin (units (pi/2) rad) 1.0_1.0 NumTest sin (units 90 deg) 1.0_1.0 NumTest (units 50 m) * sin (units 90 deg) 50.0_m NumTest ((units 50 m) * sin (units 90 deg)) :: Units (SymbolicManip Double) 50.0*sin(((2.0*pi)*90.0)/360.0)_m NumTest rpnShow $ dropUnits $ ((units 50 m) * sin (units 90 deg)) 50.0 2.0 pi * 90.0 * 360.0 / sin * NumTest (units (Symbol x) m) * sin (units 90 deg) x*sin(((2.0*pi)*90.0)/360.0)_m Also, I defined this in my source file: test :: forall a. (Num a) = a test = 2 * 5 + 3 Now, it can be used: NumTest test 13 NumTest rpnShow test 2 5 * 3 + NumTest prettyShow test (2*5)+3 NumTest test + 5 18 NumTest prettyShow (test + 5) ((2*5)+3)+5 NumTest rpnShow $ test + 5 2 5 * 3 + 5 + You can grab the very early experimental code with darcs get http://darcs.complete.org/num. Haskell has no built-in support for numeric types with units, arbitrary symbols carried through computations, etc. But it was trivial to add it. This kind of extensibility is a key part of why Haskell is so amazing. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Why I Love Haskell In One Simple Example
I recently implemented some new Haskell numeric types that, instead of performing calculations, can generate a rendering of the requested calculation or store units with it. good old Haskell rule (with apologies to Daniel Düsentrieb, I think;): impossible things are delayed immediately, miracles may take a little longer you can't get an expression representation from a value, but you can generate a representation while building the expression, so that you have it at hand if/when needed. I did something similar once (pairing values with representations instead of calculating values from representations), which you might find interesting for comparison (note that the focus in this one was on simplicity, eg. string representation only, no simplification, etc.): http://www.cs.kent.ac.uk/~cr3/toolbox/haskell/R.hs btw, that kind of thing gets even more interesting with ho-functions like foldr, foldl, map. try it!-) nice for explaining these hofs.. (the code still works, but if you use ghci -fglasgow-exts instead of hugs +98, the defaulting doesn't seem to kick in, so you'll need to give explicit type annotations, eg. map (+) [1..4::R Integer] or foldl (-) 0 [1..4::R Integer]). cheers, claus --- Do you have late-breaking research results in FP but have missed the other deadlines? Submit to TFP'05: http://www.tifp.org/tfp05/ --- extended abstracts: 8th July 2005 full papers: 2nd September 2005 symposium: 23/24 September 2005, Tallinn, Estonia (w.ICFP/GPCE) --- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell] Dynamic binding
Ralf Lammel [EMAIL PROTECTED] writes: and a related paper by Jacques Garrigue, where he proposes to solve it using OCaml's polymorphic variants. I am not sure. Is this referring to Objective Label? Which paper exactly? I think it refers to http://wwwfun.kurims.kyoto-u.ac.jp/%7Egarrigue/papers/variant-reuse.ps.gz and the expression problem seems to be the one described in: http://www.daimi.au.dk/~madst/tool/papers/expression.txt Benedikt ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe