Re: [Haskell-cafe] US Patent for the idea of using Haskell to implement UAX #9
Daniel Fischer wrote: Am Freitag 16 April 2010 20:50:25 schrieb Brian Hulley: revealed a link to a US Patent (7120900) for the idea of implementing the Unicode Bidirectional Algorithm (UAX #9 http://www.unicode.org/reports/tr9) in Haskell, making use, as far as I can tell, of nothing more than the normal approach any functional programmer would use, namely separation of concerns etc. In which case the patent should be null and void since obvious ideas aren't patentable, AFAIK. But of course, IANAL, you never know what jurists think a law means, ... Hi Daniel, Thanks for your reply. The main problem for me is just the fact that the legal system in itself is, as Charles Dickens wrote in The Old Curiosity Shop (Chapter 37): ... an edged tool of uncertain application, very expensive in the working, and rather remarkable for its properties of close shaving, than for its always shaving the right person. I just think somehow we should be free to write any programs we want just like composers can compose music, (as long as we don't just copy other people's actual copyrighted *code* without their permission of course). After all, there is no reason why people couldn't just keep their ideas a secret if they don't want others to use them: at least it wouldn't spoil things for everyone else. Companies could even charge for *access* to these secrets and people could sign NDAs, but this isn't the same as being allowed to actually own an idea itself. The current situation is a bit like a supermarket throwing oranges and apples at passers-by, then forcing people to pay if they were hit... In any case after signing the petition I'm going to just try and forget about the problem! ;-) Cheers, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: US Patent for the idea ...
jerzy.karczmarc...@info.unicaen.fr wrote: Brian Hulley reports a search similar to : haskell unicode bidirectional Comment irrelevant to Haskell, sorry. Everybody does his/her various jobs. But I lost all respect due to people who work in the US Patent Office, when I saw the patent 6,025,810, a patent for an antenna which sends signals faster than light, using some mysterious new dimension. Or the U.S. Patent 6,960,975 for an anti-gravity device. It seems that although it is illegal to break some local regulations, the idea of breaking fundamental physical laws remains perfectly legal. (In some countries...) Somebody finally decided to ridiculise the system. If you want a good laugh, see the patent 6,368,227. The search site is here: http://patft.uspto.gov/netahtml/PTO/srchnum.htm Best regards. Jerzy Karczmarczuk ... Hi Jerzy, Yes that one is very funny. Also the existence of the other patents just show how ridiculous the system is. So thanks, that humour has helped me get back down to earth and away from all kinds of fruitless imaginations about the state of the world. I think my mind is best suited to functional programming *only*... ;-) Cheers, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: US Patent for the idea ...
Murray Gross wrote: On Sat, 17 Apr 2010, Brian Hulley wrote: see the patent 6,368,227. The search site is here: http://patft.uspto.gov/netahtml/PTO/srchnum.htm Best regards. Jerzy Karczmarczuk ... It's really almost not fair to cite that particular patent, since, if I recall the story correctly (I may be wrong in small detail, but I am sure of the general picture), that patent was filed by an attorney as a demonstration to his son how the system works. It was never filed as a serious patent. Yes, it may show how poorly the examiners are doing their job, but I think this particular patent really doesn't reflect on the poor service we are currently receiving from the entire patent system--I would like to think that the examiner knew perfectly well that this patent was not serious and was willing to play along. Hi Murray, Point taken about patent 6,368,227. I think in all fairness to examiners that in a way they have an impossible job due to the fact that what is a clever idea to one programmer will be a trivial idea to another: the field is so huge and people have such different experiences. Coming back to patent 6,368,227 one could perhaps look past the humour and see it as a kind of indication of what the patent system is trying to do to humanity. I just mean to see this dispassionately as an image, and by trying to do I'm just anthropomorphizing what I see as a purely structural phenomenon that in itself is like a force of nature, that emerges from the inevitable incompleteness of people's understandings even if each person individually is trying to do what they feel is right. In terms of a way forward for research companies I think there is a lot of well-paid work to be found in designing and implementing useful libraries of functionality, and then licensing them for inclusion in other programs. After all, end users want a real implementation not just an idea, and it is surely much easier to trade implementations rather than to try to trade the rather nebulous concept of ideas. This would allow programmers full freedom to implement whatever they like together with the clear advantage of being able to license well designed third-party libraries: we'd have total clarity and freedom. Anyway I've said enough about software patents so I'll leave the discussion here and reiterate that all I want is for people to be able to write programs without a Sword of Damocles hanging over their heads. Cheers, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] US Patent for the idea of using Haskell to implement UAX #9
Hi everyone, It's been a long time since I last posted to this list since I'm currently working on something that is not directly Haskell-related, but it still relates to functional programming in general. Anyway imagine my surprise when an innocent search for some keywords (I can't remember the exact ones but the following gives similar results) haskell unicode bidirectional revealed a link to a US Patent (7120900) for the idea of implementing the Unicode Bidirectional Algorithm (UAX #9 http://www.unicode.org/reports/tr9) in Haskell, making use, as far as I can tell, of nothing more than the normal approach any functional programmer would use, namely separation of concerns etc. The link is http://www.freepatentsonline.com/7120900.html though I think it would be better if they had just called the website free handcuffs online because that is what it amounts to when people succeed in preventing others from using ideas, especially ideas everyone would easily think up by themselves. Before going further I would like to explicitly state that I would not wish to cast any aspersions upon the people or companies involved in this patent, since it is all too clear to me that these people have acted in a perfectly legal way and are just doing their various jobs: in other words it's an I'm a lumberjack and I'm ok... kind of scenario: everyone probably thinks of themsevles as being a perfectly nice upstanding person, and if I met any of them face to face I'm sure I would find that they are *indeed* really nice friendly people who believe that they are doing absolutely the right and logical thing. In fact many nice people I myself have talked to about my own ideas immediately suggest that I should obviously patent them: it takes a long time to explain to them why this would not actually further my goals at all, and it is difficult for them to understand my explanation because the problem is rather too subtle for people who have not already been thinking along these lines for a while. However all this does not affect the problem that this patent acts as a brick in the general structural evil in our world today: anyone who is trying to create a programming language environment that is accessible to people who use right-to-left languages is now between a rock and a hard place when it comes to implementing UAX #9, the standard Unicode algorithm for implementing the Unicode semantics of bidirectional text. In this particular case, I expect (but I'm not a lawyer so please don't take this as solid advice: it's just a hope) that a workaround for Haskell programmers would be to discard their natural desire to use a functional approach and instead just implement UAX #9 verbatim using the ST monad. (The patent also tries to extend itself to other functional languages so caution is needed all round.) But although the above workaround *might* be legal in this particular instance it seems to me that as programmers we must not just let our craft be dominated by the psychopathic tendencies of certain elements in society that work hard to try to squash the ``normals'' into a life of brutal misery while they rampage ruthlessly about with a biological inability to experience empathy for other human beings. (www.ponerology.com) The memetic virus of psychopathy is rapidly spreading throughout human civilization and most people are not conscious enough of the elements that are contributing towards their own behaviour, thus ignoring the fact that the rice they eat for supper might have been picked by a tiny little girl in China with bleeding fingers or the carpet they walk on may have been made by a little 8 year old boy slave chained all day to a loom in a shed in India. To this end I humbly appeal to everyone here to please help in the fight against software patents, so that we can begin the huge task of reclaiming our world for real people who understand that true meaning in life comes from extending our feeling of self into the world beyond our own body: http://petition.stopsoftwarepatents.eu/ http://ffii.org Thanks a lot for reading this, Brian. [expecting to be crucified, but if it helps just one little girl or boy it will be worth it!] Disclaimer: this email is entirely my responsibility and I am not acting on behalf of any of the above web sites. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Looking for a more functional way to do this
Jefferson Heard wrote: Adrian, my understanding is that it's not that simple, because I need to preserve the state between calls to GLUT's callbacks, which all return IO (). 2008/8/6 Adrian Neumann [EMAIL PROTECTED]: There is the State Monad... data ProgramState = ProgramState { some_associative_data :: Map String String , position :: GL.Vector3 Float , look_at :: GL Vector3 Float , selectables :: Map GLuint NamedObject } render :: IORef ProgramState - IO () You might find it easier to think in terms of a Reader monad where each component of your ProgramState above is now a separate IORef. Then you can just use a function: mkCallback :: ReaderT ProgramStateRefs IO () - IO () to create the necessary callbacks for GLUT, and there is no need to interleave any state between calls (since it's all kept in the IO monad directly). Eg: data ProgramStateRefs = ProgramStateRefs { some_associative_data :: IORef (Map String String) , ... } main = do r - createProgramStateRefs let mkCallback :: ReaderT ProgramStateRefs IO a - IO a mkCallback (ReaderT r_ma) = r_ma r GLUT.renderCallback $= mkCallback onRender ... onRender :: ReaderT ProgramStateRefs IO () onRender = do ... You can then go further and use phantom types to build specialized monads by newtyping the (ReaderT ProgramStateRefs IO) to limit the operations possible in each callback (e.g. to prevent calls to rendering methods inside a keyboard handler etc) though at some point there is a tradeoff between how much you really need to enforce statically and how much time you have to devise suitable schemes of phantom type parameters to enforce it. (Disclaimer: the above code is untested and may contain errors ;-) ) Regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Capitalization and associated type families
Jonathan Cast wrote: It's weird. ML-derived languages are functional languages at the value level (and have regular lambda-bound variables in consequence), but are logical languages at the type level (and have logical variables in consequence). So ordinary lambda-bound variables, like in ML-style functors (parametrized modules) act more like type constants than like type variables. Thanks - the above seems to be a promising avenue of thought to arrive at clarity regarding case distinctions at the type level, and I can see here the basis for a good argument of why there would actually be no inconsistency regarding the use of capitals for module type members and lowercase for the class parameters. Perhaps this is also the root of the difference between associated type synonyms and class params. Ie at the type level, uppercase == functional variable (aka constant) and lowercase == logic variable... The type level now seems to me to be quite significantly more complicated than the value level due to the mixing of functional and logic programming, not to mention that at the type level variables in an outer scope become constants in an inner scope as far as pattern matching is concerned whereas for value patterns variables are always fresh and never scoped (over other patterns). Therefore I've decided to deal with the issue of case at each level separately since it seems immediately clear that the case distinction at the value level, as in Haskell/OCaml/Moby, is obviously good due to the foolproof nature of value patterns you pointed out, whereas at the type level it may also be good but I'll need a few more months to think about it... ;-) Cheers, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Capitalization and associated type families
Tillmann Rendel wrote: Brian Hulley wrote: class Foo a where f :: a - b - (a, b) Here there is no capitalization distinction in the type of (f) but the implementation can still insert the forall b. since (a) is already in scope. Therefore similarly, if type constructors like List were instead written using lowercase, since they would already be in scope it would be clear even without explicit quantifiers that (a) and (b), but not (list), were to be quantified in the type of (map) (assuming of course that there was no top level data decl for (a) or (b)). So adding b to the export list of an imported module would change the type of f? Yes, if the module in which the above class decl were defined imported a data type (b) from some other module (or defined it elsewhere in the same module) then (f)'s type would change. (Of course at the moment this can't happen because (b) is lowercase so it can't be introduced by data/type decls or imported/exported.) The type of (f) would also change if Haskell were extended to support nested classes: class Bar b where class Foo a where f :: a - b - (a, b) But as Jonathan pointed out this behaviour is not really all that ideal since even in Haskell at the moment a simple spelling mistake could cause silent quantification instead of an error (which is perhaps the main justification for why constructors introduced by data/type decls must currently be capitalized -- unfortunately there is no corresponding protection when writing types inside class decls): class Zap a where g :: a - ^ oops! Cheers - Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Capitalization and associated type families
Hi, I'm familiar with the capitalization rules for identifiers in Haskell and know that they are very useful and practical e.g. by allowing variables to be distinguished from constants in patterns etc. However I'm trying to understand on a much deeper level whether or not they can really be justified and indeed if there is a danger that they can lead to inconsistency in the light of future extensions to the language. For example, why is there any distinction between a type variable and a type constant? To make this clearer consider the type of (map): (a - b) - List a - List b (ignoring the special [] syntax for list types which would just confuse the issue here). With explicit quantifiers, we'd write: forall a b. (a - b) - List a - List b Now this begs the question: why does List need to start with a capital? (supposing that quantifiers were always written explicitly) The same distinction between constants and variables is also used in predicate logic e.g. On(x, Table) Colour(x, Red) but similarly the above could surely be written just as easily by: exists x. on(x, table) colour(x, red) where (on), (table), (colour), and (red) are just considered to be variables that have already been introduced (by some enclosing scope) instead of having to think of them as constants and make a distinction between constant and variable. Anyway to get to the point of this post what I'm really trying to find is some explanation of why there is the concept of constant as opposed to variable or whether this concept is now redundant in the light of lexical scoping/ explicit quantification? Somewhat related to this issue is the syntax of associated type families. For example in section 5.2.2 of http://www.haskell.org/haskellwiki/GHC/Indexed_types there is the example: class C a b where data T a which raises in my mind several questions: 1) Why is (T) given a parameter? I.e. why does an associated type declared inside a class decl not automatically get all the parameters of the class passed to it so that one would just write: class C a b where data T f :: T - T === data family T a b class C a b where ... f :: T a b - T a b 2) Compare: class C a b t | a b - t with class C a b where data T In other words, why is (T) a constant when it is declared inside the class but a variable when passed as a parameter? Is the fact that (T) needs to be given a parameter even when it is declared inside the scope of the class type parameters the result of needing to fulfill the idea of constant vs variable? 3) In the syntax: class C a b data T a it seems rather odd that the a in T a should be related to the a in C a b since one might expect that the name chosen for a parameter should be local to the data decl. Apologies for such a rambling post. I've spent literally at least 6 months scouring the internet trying to find a real discussion about capitalization rules because I'm trying to answer the following question: if I make use of a similar capitalization rule in my own language, can I guarantee that this rule will not lead to an inconsistency at some future point? Ie is there a real rock solid theoretical basis for making a distinction between constants and variables that holds even in the presence of lexical scoping? Thanks, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Capitalization and associated type families
Jonathan Cast wrote: On Mon, 2008-08-04 at 19:51 +0100, Brian Hulley wrote: For example, why is there any distinction between a type variable and a type constant? forall a b. (a - b) - List a - List b Now this begs the question: why does List need to start with a capital? (supposing that quantifiers were always written explicitly) AFAIK, it doesn't; the variable/constant distinction is just there to let the implementation put the foralls in for you. Hi Jonathan - thanks - this confirms what I've been thinking. However consider: class Foo a where f :: a - b - (a, b) Here there is no capitalization distinction in the type of (f) but the implementation can still insert the forall b. since (a) is already in scope. Therefore similarly, if type constructors like List were instead written using lowercase, since they would already be in scope it would be clear even without explicit quantifiers that (a) and (b), but not (list), were to be quantified in the type of (map) (assuming of course that there was no top level data decl for (a) or (b)). Similarly, if we had explicit foralls on equations, we could say forall n x xn. drop (n+1) (x:xn) = drop n xn but forall n. drop n nil = nil and it would be perfectly clear that `nil' in the latter case was a constructor. Actually I quite like the above because it shows that pattern matching can be understood in terms of universally quantified predicates. Regarding the verbosity, patterns are something of a special case since variables (that are introduced in the pattern) can only occur once and there is no need to have higher rank quantification in value patterns (disregarding explicit tests for _|_). Therefore special syntax could be used to make the above shorter e.g. borrowing the '?' from Felix (http://felix.sourceforge.net/doc/tutorial/introduction/en_flx_tutorial_top.html (section 2.11/2.17 etc)): drop (?n + 1) (_ : ?xn) = drop n xn drop ?n nil = nil (where glued prefix binds tighter than application). Of course, if you want to introduce this rule, you'd better start out with it and be consistent --- require every variable to be explicitly brought into scope. I think you'd find it pretty annoying after trying to program in your new language for a while, though. I agree that there are many good points in favour of Haskell's use of a case distinction, not the least being that it gives definite guidance on when to use lower or upper case identifiers and therefore avoids the mess you find in C++ programs where every programmer has their own private conventions which can lead to confusion and useless debate. However it still seems to me that the case distinction, at least on the level of type constructors, becomes problematic and possibly inconsistent especially if I consider the effects of trying to incorporate something like the ML module system as well as type classes. (For example the Moby language (http://moby.cs.uchicago.edu/ ), a possible successor to SML, uses capitalization for type constructors similar to Haskell which means that type parameters in functor applications must be uppercase, which conflicts with the use of lowercase type params for classes which are a special kind of functor... (Moby itself doesn't encounter any difficulty since it doesn't have type classes)). Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Dynamic choice of reverse implementation
Krzysztof Kościuszkiewicz wrote: Fellow Haskellers, I wanted to experiment a bit with lists and sequences (as in Data.List and Data.Sequence), and I got stuck. I wanted to dynamically select processing function depending on cmdline argument: main = do args - getArgs let reversor = case args of [sequence] - reverseList [list] - reverseSeq _ - error bad args input - getContents let output = reversor $ lines $ input mapM_ putStrLn output In my oppinion reversor would have type reversor :: (Foldable f) = [a] - f b No, this is the wrong type. To find the correct type, if you look at the type of the input argument in your code it will be the result of (lines), so from ghci: Prelude :t lines lines :: String - [String] Prelude Therefore (reverseor) has type [String] - ??? Now for the output type, you are using (output) as an input to (mapM_ putStrLn). (mapM_) takes a list and uses its argument to do something to each element of the list. So, since the input to (putStrLn) is (String), the input to (mapM_ putStrLn) is ([String]). Therefore reversor :: [String] - [String] So reverseList is just Data.List.reverse as you've got it (though presumably you meant to write [list] - reverseList and not reverseSeq). For using Data.Sequence to implement reversor, all you need to do is first convert [String] to Seq String, reverse the sequence, then convert back from Seq String to [String]. Hope this helps, Brian. but I couldn't get this to work. I've tried typeclass approach: class (Foldable f) = Reversor f where reverse' :: [a] - f a instance Reversor ([]) where reverse' = Data.List.reverse instance Reversor ViewR where reverse' = viewr . foldr (|) empty reverseList = reverse' :: (???) reverseSeq = reverse' :: (???) but now in order to differentiate between reverse' functions I'd have to provide different type annotations, and then reversor won't typecheck... Similar problem surfaced with this try: data Proc = SP | LP reverseList = reverse' LP reverseSeq = reverse' SP reverse' :: (Foldable f) = Proc - [a] - f a reverse' LP = Data.List.reverse reverse' SP = viewr . foldr (|) empty So now I'm looking for some suggestions how should I approach the problem... Regards, ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Dynamic choice of reverse implementation
Brian Hulley wrote: Krzysztof Kościuszkiewicz wrote: So the type of mapM_ used in the code is (Foldable t, Monad m) = (a - m b) - t a - m () I'd like to keep the generic Foldable t there when m is specialized to IO. I thought this would allow type of reversor to be specialized to (Foldable f) = [String] - f String ... I'd like to avoid [a] - something - [a] Yes this type should be fine. I should have said though that in your code, because one arm of the case construct returns Data.List.reverse, the type of reversor is fixed to [a] - [a]. The other arm of the case construct could make use of a more general function eg reverseFoldable :: (Foldable f, Foldable g) = f a - g a but it would only be used at f == [], g == []. So in terms of the command line test harness, I think the only way is to explicitly choose the foldable you want to try out eg by using (Foldable.toList . Seq.reverse . Seq.fromList) etc. An alternative might be to just write some different implementations of reverse functions in a module then load the module into ghci to test them out interactively so their types don't get unified with each other. Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Dynamic choice of reverse implementation
Krzysztof Kościuszkiewicz wrote: So the type of mapM_ used in the code is (Foldable t, Monad m) = (a - m b) - t a - m () I'd like to keep the generic Foldable t there when m is specialized to IO. I thought this would allow type of reversor to be specialized to (Foldable f) = [String] - f String ... I'd like to avoid [a] - something - [a] Yes this type should be fine. To implement reversor though you'd still need to first convert from the concrete list to whatever foldable you're using, before reversing the foldable, or implement something more general eg: reversor :: (Foldable f, Foldable g) :: f a - g a Of course with lazy evaluation + compiler optimizations the lists in [a] - something - [a] should be erased at compile time... ;-) Regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Desugaring of infix operators is (always?) the wrong way round
Sam Hughes wrote: Brian Hulley wrote: ... For example, with the prefix definition of a function with multiple clauses, the function name at the start of each clause is already lined up since it must appear at the margin of the current layout block ... Or you could have everything be backwards, and use an editor that right aligns things. (a - b) - [a] - [b] :: map [] = [] _ map x f : xs f map = (x:xs) f map There is still a reversal here between the order of arguments in the type signature and the order in the clauses. Henning Thielemann wrote: Curried functions like f :: a - b - c suggest a swapped order of arguments for (-), since 'f' must be called this way b a f Maybe it should be f :: c - b - a Which would fix this reversal. However there are 2 other kinds of reversal with postfix notation: 1) Declarations start with a keyword followed by some content whereas function definitions start with the args followed by the function name 2) Special constructs like case or let have to start with the keyword (so the parser knows what kind of thing it is supposed to parse next and so that the editor knows how to highlight what the user is typing before the user has finished typing the whole construct), again making a reversal between built-in constructs and constructs you can define using higher order functions (eg consider if as a user-defined construct in a postfix language) I've come to the conclusion that whereas postfix notation is extremely neat for simple stack-based languages like Forth and PostScript it would not play well with languages which have a structured syntax since structured syntax + left to right reading order implies each syntactic element must start with a head followed by content appropriate to that element, or else recursive descent parsing and/or as-you-type grammatical highlighting would be impossible, and therefore in terms of function application, the head must of course be the function itself hence Prefix is the only solution. Jonathan's comparison to natural languages made me think of it this way: x `plus` y === [Subject] [Verb] [Object] x .plus(y) === [Subject] [Verb Object] plus y x === [Verb Object] [Subject] plus x y === [Verb Subject] [Object] which illustrates why infix notation feels natural (corresponds to SVO in English etc), why OOP notation feels natural, why prefix notation is natural for a functional language (since we are interested primarily in the transformation not the things being transformed hence we put [VO] first), and why the desuraging of infix in Haskell/ML is quite simply just wrong, since the object is now separated from the verb. ok wrote: Binary operators have two arguments. That's why sections are needed. What's wrong with just using (flip)? I am a bear of very little brain, and I would find it VERY confusing if the order of arguments in an operator application did not match the order of arguments in a function call. I can live with x @ y = (op @)(x, y)(* SML *) x @ y = (@) x y-- Haskell but making the orders different would guarantee that I would *always* be in a muddle about which argument was which. Living with inconvenient argument orders is vastly easier than with inconsistent ones. If you inwardly parse x @ y as [x] [@ y] then the prefix notation is naturally formed just by putting the specialized verb before the subject instead of after it ie [@ y] [x]. Therefore I think this desugaring, though different from the usual one, would seem natural as soon as the reason for it was understood (of course, only if you agree with the reason ;-) ), and the great advantage of it is that we could write library functions without having to decide in advance whether or not they should be used with infix sugar. (Regarding Henning's point about ((-) a) being needed for Reader monads we could define type Fun a b = a - b and then use (Fun a)) In any case, thanks to all who replied. I've found the discussion very illuminating and it's certainly helped a lot to clarify the issues for me, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Desugaring of infix operators is (always?) the wrong way round
Hi, I'm in the process of designing a little language inspired by Haskell but imperative, and have hit an issue regarding infix syntax which may be of interest also to anyone thinking about future revisions of Haskell or the problem of consistent parameter order in libraries. I'm wondering if anyone can shed light on the reason why x # y gets desugared to (#) x y and not (#) y x since the first desugaring always seems to lead to (#) having to be defined in a way that is unnatural for functional programming. This is why a lot of functions in the standard libraries have their arguments the wrong way round. For example in Data.Bits we have: shiftL :: a - Int - a whereas the natural argument order for a functional language would be to make it so that in an application one has the verb first followed by the noun as in: shiftL' :: Int - a - a so we could write (shiftL' 3) to denote the operation of shifting something left by 3 eg: let shiftLeftByThree = shiftL' 3 in map shiftLeftByThree [10, 78, 99, 102] (This choice of argument order is explained at http://www.haskell.org/haskellwiki/Parameter_order ) Similarly, considering arithmetic, it would make a lot more sense to me to define: x - y === (-) y x since the action here is take away y and the noun is x so the natural functional reading of (-) a b is subtract a from b. To be consistent this would also have to apply to the use of (-) in types to get: a - b === (-) b a Can anyone think of an example where the current desugaring of infix arguments gives the correct order when the function is used in a postfix application? (apart from commutative functions of course!) Thanks, Brian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Desugaring of infix operators is (always?) the wrong way round
Brian Hulley wrote: I'm wondering if anyone can shed light on the reason why x # y gets desugared to (#) x y and not (#) y x Can anyone think of an example where the current desugaring of infix arguments gives the correct order when the function is used in a postfix application? (apart from commutative functions of course!) Sorry I meant to write *prefix* application ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Desugaring of infix operators is (always?) the wrong way round
Jonathan Cast wrote: On Tue, 2007-09-25 at 19:18 +0100, Brian Hulley wrote: Brian Hulley wrote: I'm wondering if anyone can shed light on the reason why x # y gets desugared to (#) x y and not (#) y x Of course, this is all a consequence of the well-known failure of natural language: verbs come before their objects. It is thus natural to write f(x), when in fact it is the object that should come first, not the function. Switching to a (natural) language where (finite) verbs come at the end of sentences, where they belong, should fix this issue in time. Doing the same in a functional language would be ideal as well, but might limit its use among those who speak inferior natural languages. Thanks, I must look into using postfix notation. It's used in Forth and Postscript and I seem to dimly recall that there is a natural language somewhere that also uses it but I can't remember which one. Not only would it solve the infix/prefix dilemma, but it would also be consistent with a sugar for an object oriented syntax for application: a b c f a .f(b, c) (Using a dot glued on its right and a left paren glued left to avoid ambiguity with unglued dot (function composition) and unglued left paren (unit/tuple/bracketing)) It's not so clear to me what the syntax for types should be in a postfix language. Also, a problem might be that it is not so easy to use the multiple-clause style of function definition eg compare: map _ [] = [] map f (h : t) = f h : map f t with [] f map = [] (h : t) f map = h f : t f map since the function name is no longer conveniently at the margin of whatever layout block we are in so extra efforts would need to be made to line them up, though this is a minor issue. Thanks again, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Desugaring of infix operators is (always?) the wrong way round
Ryan Ingram wrote: My comments inlined below... On 9/25/07, Brian Hulley [EMAIL PROTECTED] wrote: let shiftLeftByThree = shiftL' 3 in map shiftLeftByThree [10, 78, 99, 102] let shiftLeftByThree = (`shiftL` 3) in ... Aha! but this is using section syntax which is yet another complication. Hypothesis: section syntax would not be needed if the desugaring order was reversed. Can anyone think of an example where the current desugaring of infix arguments gives the correct order when the function is used in a postfix application? (apart from commutative functions of course!) A couple off the top of my head: (:) :: a - [a] - [a] Yes that's one that had totally slipped my mind ;-) | :: MonadPlus m = m a - m a - m a (how do you define correct in this case, anyways?) I'm not so sure about this one eg: first | second (trychoice second) first because (trychoice second) encapsulates what to do when its argument action fails. Even for shift I can think of several reasons to want to use it both ways; for example, unpacking a bitfield from a Word16: unpack v = (getM 0 255, getM 8 1, getM 9 31, getM 14 3) where getM = (..) . (shiftR v) I suppose with some ops perhaps there is no most common way of wanting to use them and hence no one-true-way argument order for those ops. Thanks for the examples, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Desugaring of infix operators is (always?) the wrong way round
Dan Piponi wrote: On 9/25/07, Brian Hulley [EMAIL PROTECTED] wrote: ..I seem to dimly recall that there is a natural language somewhere that also uses it but I can't remember which one. Every permutation of [S,V,O] appears in 'nature': http://en.wikipedia.org/wiki/Word_order. Thanks for the link - I see [Subject, Object, Verb] is actually the most common word order. Also, a problem might be that it is not so easy to use the multiple-clause style of function definition I disagree, it's easier with postfix functions. With prefix functions, to get line-up you insert space in the middle of the line. With postfix notation you would often insert space at the beginning of a line, a much easier place to insert text, because there is a keystroke, in most text editors, to take you to the beginning of a line. I don't understand what you mean. For example, with the prefix definition of a function with multiple clauses, the function name at the start of each clause is already lined up since it must appear at the margin of the current layout block (especially if you follow the simple rule of always following a layout starter token by a newline rather than starting a new multi-line layout block in the middle of a line), whereas with the postfix notation you'd need to manually line up the function names if you wanted the same neat look. It's not so clear to me what the syntax for types should be in a postfix language. Postfix, of course! So you'd write data a Tree = Leaf | a a Tree Sorry I meant what should the syntax of type declarations for functions be? For example, with prefix map (writing lists without sugar for clarity) we have: map :: (a - b) - List a - List b map _ Empty = Empty map f (PushF h t) = PushF (f h) (map f t) The occurrence of map in the type decl lines up with the 2 occurrences of map in the clauses, and the types of the arguments are in the same order in the type as in the patterns in the clauses. A postfix version could be: map :: (a - b) - a List - b List Empty _ map = Empty (h t PushF) f map = (h f) (t f map) PushF but now the occurrences of map no longer line up and the argument order is reversed between the type and the value syntax. Of course the problem disappears if you just discard multiple clause syntax and use: (list :: a List) (f :: a - b) map :: b List = case list of Empty - Empty h t PushF - (h f) (t f map) PushF Confusingly, ocaml does something like this, with postfix notation for types and prefix notation for function application. I've never understood why {Oca, S}ML's creators decided to make life so difficult and confusing by introducing an arbitrary reversal between type and value syntax. ;-) Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Syntax for lambda case proposal could be \of
Hi, On http://hackage.haskell.org/trac/haskell-prime/wiki/LambdaCase the proposed syntax for lambda case is: case of alts but this has a really bad downside for interactive editors: it doesn't allow one to distinguish between an incomplete construct and a completed construct thus removing one opportunity for an editor to alert the user (eg by highlighting) that there is something missing in the program text. Therefore I propose: \of alts which doesn't suffer this problem since the keyword of can never follow a '\' in the existing grammar. However I can't edit the H' wiki, so if anyone agrees that the above syntax is better please could they add the above to the page. Thanks, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Syntax for lambda case proposal could be \of
Stefan O'Rear wrote: On Wed, Aug 15, 2007 at 06:58:40PM +0100, Duncan Coutts wrote: On Wed, 2007-08-15 at 10:50 -0700, Stefan O'Rear wrote: OTOH, your proposal provides (IMO) much more natural syntax for multi-pattern anonymous functions, especially if we stipulate that unlike a case (but like a lambda) you can have multiple arguments; then you could write stuff like: sumTo0 = foldr (\of 0 k - 0 n k - n + k) 0 sumTo0 = foldr (\0 k - 0 n k - n + k) 0 foo = getSomethingCPS $ \ arg - moreStuff is now a syntax error (\ { varid - } matches no productions). A multi-way lambda could be introduced using \\ thus: sumTo0 = foldr (\\ 0 k - 0; n k - n + k) 0 [from a previous post] It's not like the current language has that property; consider (map myFunction) - is that an error or a partial application? By construct I meant only those grammatical elements involving keywords, and was thinking about situations where you might for example have various syntax templates bound to function keys eg in Haskell the following are incomplete: case of if then else data where deriving (let in could still be marked as incomplete even if it is ok according to the grammar since it would be weird to bother writing a let with no bindings.) There is a similar problem with the way template haskell uses unmatched quotes such as 'a so it's no longer possible to determine whether this should be marked as an incomplete character literal or a complete TH name. I suppose my main point is that it's useful for a syntax to have plenty of unfilled gaps that result in an error when written rather than filling all those gaps with different meanings... Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Language support for imperative code. Was: Re: monad subexpressions
Brian Hulley wrote: apfelmus wrote: Brian Hulley schrieb: main = do buffer - createBuffer edit1 - createEdit buffer edit2 - createEdit buffer splitter - createSplitter (wrapWidget edit1) (wrapWidget edit2) runMessageLoopWith splitter ... Thus the ability to abstract mutable state gives to my mind by far the best solution. I'm not sure whether mutable state is the real goodie here. I think it's the ability to indpendently access parts of a compound state. http://www.st.cs.ru.nl/papers/2005/eves2005-FFormsIFL04.pdf This is indeed a real key to the problem. Of course this is only one aspect of the problem... Thinking about this a bit more, and just so this thought is recorded for posterity (!) and for the benefit of anyone now or in a few hundred years time, trying to solve Fermat's last GUI, the object oriented solution allows the buffer object to do anything it wants, so that it could negotiate a network connection and implement the interface based on a shared network buffer for example, without needing any changes to the client code above, so a functional gui would need to have the same flexibility to compete with the OO solution. Another thing that would be interesting would be to have a formal treatment of what is supposed to happen in a gui. For example, when you move the mouse over a control which has become dirty (ie needs to be re-rendered because its state is now inconsistent), what should the control do? Should it respond as if the new state were already visible to the user, or should it interpret the mouse position according to the last state that was rendered, or should it just ignore all mouse events until the next time it gets rendered? This is not a trivial question because you could imagine an animated control where the user might naturally be following the movement, whereas when the user clicks on a cell in a spreadsheet when the cells to the left have now expanded due to a change in data thus moving the cell along (but where this updated model has not yet been re-rendered) the user might be irritated at the wrong cell being selected... It's tricky little issues like this that I haven't found any documentation for anywhere, and which would make a proper mathematical treatment of interaction with a gui very useful, regardless of whether it is implemented in OOP or functional style. Anyway just a thought, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Language support for imperative code. Was: Re: monad subexpressions
apfelmus wrote: Brian Hulley schrieb: main = do buffer - createBuffer edit1 - createEdit buffer edit2 - createEdit buffer splitter - createSplitter (wrapWidget edit1) (wrapWidget edit2) runMessageLoopWith splitter ... Thus the ability to abstract mutable state gives to my mind by far the best solution. I'm not sure whether mutable state is the real goodie here. I think it's the ability to indpendently access parts of a compound state. In other words, the IORef created by buffer is a part of the total program state but you can access it independently. There is a functional idiom for that, see also Sander Evers, Peter Achten, and Jan Kuper. A Functional Programming Technique for Forms in Graphical User Interfaces. http://www.st.cs.ru.nl/papers/2005/eves2005-FFormsIFL04.pdf Thanks for this reference. This is indeed a real key to the problem. (Though a possible downside with compositional references might be efficiency as the modified sub-state needs to be injected back into a new composite state but perhaps the solution here would be to have uniqueness typing as in Clean so that these injections could hopefully be erased at compile time.) I think one of the issues with Haskell is that there are so many features to choose from it is difficult to know how to approach a problem eg for streams you can have 1) A lazy list 2) A typeclass with get and pushBack methods 3) An object using an existential to wrap (2) 4) A record containing get and pushBack methods 5) A monad with get and pushBack actions 6) A simple function wrapped in a newtype: newtype Stream a = Stream (() - Maybe (a, Stream a)) and I tend to only discover a simple solution like (6) (which works equally well for both strict and lazy languages) after spending an enormous amount of time on 1,2,3,4,5... ;-) - For Graphics, I want to build a graphic from smaller ones and then draw it. I don't want to know how drawing is implemented and what mutable state might be involved. - For a GUI, I want to write down the data dependencies and a library converts this to a mesh of mutable state. That's what I mean with higher level functional model. I agree this would be ideal. A challenge I don't yet know how to solve, when dealing with 3d graphics, is that it seems that for efficiency it is necessary to consider a mesh of triangles to be an object with identity in order to be able to display an updated mesh (eg as the user drags a vertex with the mouse) in real time. This is because the representation of a mesh is constrained by the low level details of the graphics system eg vertices might need to be represented by a contiguous array of unboxed positions and normals, and triangles by a contiguous array of vertex indices, and it is too expensive to copy these arrays on each frame. Perhaps though this is another case where some form of uniqueness typing as in Clean could come to the rescue so one could write: createMesh :: [Vertex] - [[VertIndex]] - Mesh moveVertex :: Vertex - *Mesh - *Mesh instead of createMesh :: [Vertex] - [[VertIndex]] - IO Mesh moveVertex :: Vertex - Mesh - IO () Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Language support for imperative code. Was: Re: monad subexpressions
apfelmus wrote: However, most genuinely imperative things are often just a building block for a higher level functional model. The ByteString library is a good example: the interface is purely functional, the internals are explicit memory control. It's a bad idea to let the internal memory control leak out and pollute an otherwise purely functional program with IO-types. Hi Apfelmus, This is a really interesting discussion that touches on issues I'm currently working with (I'm designing a strict version of Haskell to explore various ideas about modules, namespace management, and how to get really efficient machine code but without losing the convenience of accurate garbage collection etc, but I'm having difficulties deciding between the monadic path and the impure path), so I've forked this new thread. Regarding the quote above, if the API must hide explicit memory control from the user the only way I can see of doing this would be to use (unsafePerformIO), which really is unsafe since Haskell relies on the fact that mutable operations can't escape from the IO monad in order to get away with not having to impose a value restriction as in ML. If you don't use (unsafePerformIO), then the slightest need for mutable data structures pollutes the entire interface. For example in the excellent paper you quoted N. Ramsey and J. Dias. An Applicative Control-Flow Graph Based on Huet's Zipper http://www.eecs.harvard.edu/~nr/pubs/zipcfg-abstract.html http://www.eecs.harvard.edu/%7Enr/pubs/zipcfg-abstract.html the authors are pleased to have found an Applicative solution, and indeed their solution has many useful and instructive aspects. However on page 111, hidden away in the definition of their API function to create a label, is a call to (ref 0) ;-) The equivalent implementation in Haskell would completely destroy all hope of using this in a pure context and force all use of the API into the IO monad. Haskell and ML seem to stand at opposite poles. Haskell is designed so that any attempt at abstracting mutable local state will infect the entire program (modulo use of a highly dangerous function whose semantics is entirely unclear, depending on the vagaries of evaluation strategy of the particular compiler) whereas people have been struggling in the ML community for at least 15 years to try and find a way to hide the fact that mutable storage is being used (cf attempts to find a proper solution to the unsoundness introduced by polymorphism and ref without having to use imperative/weak type variables etc). Meanwhile, C++, C#, and Java programmers get a type system (thinking only about static methods using generics/templates) that seems to me no less powerful than that of the prenex polymorphism of ML, yet without any of the unsoundness problems, and therefore without the need of a value restriction (afaiu this is because their template/generic definitions stand in for an infinite family of monomorphic bindings instead of ML which tries unsuccessfully to make one piece of memory represent each element of an infinite family of values simultaneously). Not only this, but there seems to me to be many problems for which it is natural to think in terms of objects with identity and mutable state. I can readily discard the concepts of deep inheritance hierarchies and open recursion but this still leaves the problem of identity and localised mutability. For example consider a simple GUI with 2 edit widgets, a splitter, and a single buffer that contains the text being edited. The idea is that you should be able to use either edit widget to interact with the same buffer eg to edit at different locations in the buffer. A simple imperative solution might be something like: main = do buffer - createBuffer edit1 - createEdit buffer edit2 - createEdit buffer splitter - createSplitter (wrapWidget edit1) (wrapWidget edit2) runMessageLoopWith splitter Here it's really clear what's happening, and different objects in the program correspond exactly to how I think about what I'm trying to do ie I want to create individual objects with identity and then plug them together. I don't want to have to bother about passing state around, or having to define a new data type every time I want a different configuration of widgets. Thus the ability to abstract mutable state gives to my mind by far the best solution. In contrast, all the pure functional GUIs that I've seen are just wrappers around someone else's imperative code, and moreover, they exchange the simplicity of the object oriented imperative API for a veritable mindstorm of unbelievably heavy, clunky, slow, inefficient, inextensible, hard to understand encodings that seem to me to have the effect of turning a high level language into some kind of circuit board (I'm thinking of arrows etc). Indeed everyone seems to be using either WxWidgets or
Re: [Haskell-cafe] Language support for imperative code. Was: Re: monad subexpressions
Martin Percossi wrote: Brian Hulley wrote: hidden away in the definition of their API function to create a label, is a call to (ref 0) ;-) The equivalent implementation in Haskell would completely destroy all hope of using this in a pure context and force all use of the API into the IO monad. Really? I would have thought this is a job for the ST monad, in which case the API can be wrapped up in a runST or similar; no need for leaking IO monads. Or am I missing something? Well I agree you're right on this particular use of a Ref, since their program is only dealing with a mapping from input to output so once they're finished using the data structure there is no longer any need for the ref and so the result can be returned to the rest of the program. However there are 2 problems with this approach in general afaics: 1) All code that uses this data structure ie that participates in the implementation of the transformations by using the API functions will have to be in a monad (ST or IO, it really doesn't matter in terms of all the perceived burdensomeness of do notation relative to normal applicative code). 2) The example doesn't transfer to an interactive situation, where we would need to keep the data structure around and use it forever - because we would be forever trapped inside the ST monad otherwise we'd lose that particular STRef which we were hoping to use to efficiently update the output in the face of a delta in the input. Corey - I found this page helpful to get an understanding of the value restriction in ML: http://www.smlnj.org/doc/Conversion/types.html The restriction was proposed by Andrew Wright in 1995: Simple Imperative Polymorphism by Wright http://citeseer.ist.psu.edu/wright95simple.html Some other related papers are: The Type and effect discipline by Talpin and Jouvelot 1992 Standard ML-NJ weak polymorphism and imperative constructs by Hoang, Mitchell, and Viswanathan Weak polymorphism can be sound by Greiner 1993 and more recently (2003) Relaxing the value restriction by Garrigue http://citeseer.ist.psu.edu/garrigue03relaxing.html (Note that even now there is still no real solution to it.) Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Language support for imperative code. Was: Re: monad subexpressions
Hugh Perkins wrote: On 8/8/07, *Brian Hulley* [EMAIL PROTECTED] mailto:[EMAIL PROTECTED] wrote: In contrast, all the pure functional GUIs that I've seen... In defense of Haskell (wow!), note that imperative languages are not without problems in GUIs. In a multithreaded environment, If you're using multiple threads you'd need to be in the IO monad to create/manipulate the MVars or TVars or whatever. (In contrast to eg AliceML where you could easily use a synchronising logic variable without having to leave all the familiar applicative coding comforts behind to brave the fiercesome lonely toil of Monadia ;-)) typically only one thread is allowed to manage the GUI, and then you typically need to set up some sort of message-passing system to communicate between this thread and the others AFAIK? This is a total PITA, so if someone has a solution for this that would rock :-) Question: to what extent do the Haskell wrappers around gtk and wxWidgets suffer from this problem? I mean, I havent tried them, so it's a genuine question. I don't know though I seem to recall some info on this on the website of Gtk2Hs. (Note: off the top of my head, in an imperative language, I guess one could use some sort of generator to take an interface and generate the message classes, and marshalling classes automatically) (Disclaimer: I havent really searched very hard for ways to handle threading in GUIs in imperative languages, since mostly I either use web pages as the visual interface, which avoids around the problem, or use a single thread, which also avoids the problem) So far I've always managed to get away with just using a single threaded GUI. I think you run into problems with XLib and OpenGL (on GNU/Linux at least) if you try to call into those APIs from multiple threads and also it seems better to separate concerns by having all rendering code, including cacheing of geometry etc, in the same thread since it's easy enough to spawn new threads to do calculations and set a flag in the relevant widget when the result is complete... Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] a regressive view of support for imperative programming in Haskell
Paul Hudak wrote: All of the recent talk of support for imperative programming in Haskell makes me really nervous ... if we give imperative programmers the tools to do all the things they are used to doing in C++, then we will be depriving them of the joys of programming in the Functional Way. How many times have we seen responses to newbie posts along the lines of, That's how you'd do it in C++, but in Haskell here's a better way Perhaps I may have sounded unappreciative of all the hard work that's been done trying to find solutions to the problem of GUI programming in a pure functional style. I think the problem is that for the purposes of research, it is sufficient to show that a concept can be implemented but the speed of the resulting program is not that important compared to the essential ideas. Thus the concept of a GUI as a time varying continuous function of events and response pictures (represented as functions:: Vector3 Float - RGB) is tremendously appealing, and will surely become the standard way when machines get fast enough, but for the moment this nice pure functional way just doesn't seem directly applicable (;-)). I see the problem you're pointing to though - that the language could become caught in the middle trying to serve two rather different purposes namely a pure ground for research and a fast general purpose platform for creating programs now. As for me, the issue is just that after spending almost 2 years with Haskell trying to find/discover a purely functional solution to this problem that will be suitable for a practical high speed graphics application on standard hardware, being unsuccessful, and not having any funding to pursue this research further, my only option is to either use the imperative monadic style of Haskell programming or to use OCaml or C++, because I need to get something written right now that I can put on my website to sell... Personally I don't find the existing do notation all that burdensome - I've got used to it, and even though each action must be explicitly written, the ease with which higher order functions can be introduced to factor out commonality means that the do blocks are often shorter than the corresponding C++ code from my previous GUI. Furthermore, even though I'm using the imperative style, the use of Haskell has led me to surprisingly neat solutions to several problems that I didn't discover when I implemented the previous versions in C++ and C#, so I think there are still great benefits to be had from using Haskell or languages inspired by it. Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie question: multi-methods in Haskell
peterv wrote: In de book Modern C++ design, Andrei Alexandrescu writes that Haskell supports “multi-methods” Using multi-methods, I could write (in pseudo code) collide (Asteroid, Planet) = an asteroid hit a planet collide (Asteroid, Earth) = the end of the dinos ... collide (Planet, Asteroid) = collide (Asteroid, Planet) collide (Earth, Asteroid) = collide (Earth, Asteroid) Hi, In Haskell you can use multi parameter type classes to solve this problem: {-# OPTIONS_GHC -fglasgow-exts -fallow-undecidable-instances -fallow-overlapping-instances #-} module Collide where class Collide a b where collide :: (a,b) - String data Solid = Solid data Asteroid = Asteroid data Planet = Planet data Jupiter = Jupiter data Earth = Earth instance Collide Asteroid Planet where collide (Asteroid, Planet) = an asteroid hit a planet instance Collide Asteroid Earth where collide (Asteroid, Earth) = the end of the dinos -- Needs overlapping and undecidable instances instance Collide a b = Collide b a where collide (a,b) = collide (b, a) -- ghci output *Collide collide (Asteroid, Earth) the end of the dinos *Collide collide (Earth, Asteroid) the end of the dinos Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie question: multi-methods in Haskell
Dan Weston wrote: Remember that type classes do not provide object-oriented functionality. The dispatch is static, not dynamic. Although OOP can be simulated in Haskell, it is not a natural idiom. If you need dynamic dispatch (including multiple dispatch), you may want to reconsider your solution. Dynamic dispatch is easily added to Haskell code by using an existential to represent any collision: {-# OPTIONS_GHC -fglasgow-exts -fallow-undecidable-instances -fallow-overlapping-instances #-} module Collide where -- Changed to a single param to make life easier... class Collide a where collide :: a - String data Solid = Solid data Asteroid = Asteroid data Planet = Planet data Jupiter = Jupiter data Earth = Earth instance Collide (Asteroid, Planet) where collide (Asteroid, Planet) = an asteroid hit a planet instance Collide (Asteroid, Earth) where collide (Asteroid, Earth) = the end of the dinos -- Needs overlapping and undecidable instances instance Collide (a, b) = Collide (b, a) where collide (a,b) = collide (b, a) -- This is how you get dynamic dispatch in Haskell data Collision = forall a. Collide a = Collision a instance Collide Collision where collide (Collision a) = collide a -- ghci output *Collide let ae = Collision (Asteroid, Earth) *Collide let pa = Collision (Planet, Asteroid) *Collide collide ae the end of the dinos *Collide collide pa an asteroid hit a planet *Collide map collide [ae, pa] [the end of the dinos,an asteroid hit a planet] Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Newbie question: multi-methods in Haskell
peterv wrote: This is very nice, but it does not really solve the original problem. To get Haskell to choose the best fit it's necessary to encode the location of each element in the hierarchy, so that elements deeper in the hierarchy are more instantiated than those at the top. Then instance selection chooses the best fit by just choosing the most instantiated match. Encoding can be done using phantom types, so a generic solid has the path IsSolid s a planet has IsSolid (IsPlanet p) and a specific planet eg Earth has path IsSolid (IsPlanet Earth) A newtype can be used to associate the path with the actual object: newtype InH path body = InH body so Earth is represented by InH Earth :: InH (IsSolid (IsPlanet Earth)) Earth A class with a functional dependency gives us the mapping between concrete objects and the objects as viewed by the hierarchy: class ToH body path | body - path where toH :: body - InH path body toH = InH The functional dependency means that the path (location in the hierarchy) is uniquely determined by the body, and instance decls then define this relationship: instance ToH Asteroid (IsSolid Asteroid) instance ToH Jupiter (IsSolid (IsPlanet Jupiter)) instance ToH Earth (IsSolid (IsPlanet Earth)) The code is below but as you can see the OOP encoding in Haskell becomes quite heavy and clunky so this style is probably not ideal for a real program - Tillmann's suggestion to use algebraic datatypes instead is more idiomatic - but anyway here goes: {-# OPTIONS_GHC -fglasgow-exts -fallow-undecidable-instances -fallow-overlapping-instances #-} module Collide where class Collide a where collide :: a - String data Asteroid = Asteroid data Jupiter = Jupiter data Earth = Earth data IsSolid a data IsPlanet a newtype InH path body = InH body class ToH body path | body - path where toH :: body - InH path body toH = InH instance ToH Asteroid (IsSolid Asteroid) instance ToH Jupiter (IsSolid (IsPlanet Jupiter)) instance ToH Earth (IsSolid (IsPlanet Earth)) data Collision = forall a. Collide a = Collision a mkCollision :: (ToH a pa, ToH b pb, Collide (InH pa a, InH pb b)) = a - b - Collision mkCollision a b = Collision (toH a, toH b) instance Collide (InH (IsSolid a) aa, InH (IsSolid b) bb) where collide _ = generic collision instance Collide (InH (IsSolid Asteroid) Asteroid, InH (IsSolid (IsPlanet bb)) cc) where collide _ = an asteroid hit a planet instance Collide (InH (IsSolid (IsPlanet a)) aa, InH (IsSolid Asteroid) Asteroid) where collide _ = an asteroid hit a planet instance Collide (InH (IsSolid Asteroid) Asteroid, InH (IsSolid (IsPlanet Earth)) Earth) where collide _ = the end of the dinos instance Collide (InH (IsSolid (IsPlanet Earth)) Earth, InH (IsSolid Asteroid) Asteroid) where collide _ = the end of the dinos instance Collide Collision where collide (Collision a) = collide a --- ghci output *Collide mapM_ putStrLn (map collide [ mkCollision Asteroid Earth , mkCollision Earth Asteroid , mkCollision Jupiter Asteroid , mkCollision Asteroid Jupiter , mkCollision Asteroid Asteroid ]) the end of the dinos the end of the dinos an asteroid hit a planet an asteroid hit a planet generic collision *Collide Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: monad subexpressions
On Fri Aug 3 06:06:31 EDT Neil Mitchell wrote: What are the semantics of do b f (- a) where does the evaluation of a get lifted to? I suggest the execution of (a) should be done immediately before the action obtained by applying the monadic function whose argument it is part of: do b ( a = \ra - f ra) Similarly, I'd desugar if (- a) then f (- b) else g (- c) to a = \ra - if ra then (b = \rb - f rb) else (c = \rc - g rc) I think it would just be confusing to have to think about lines in the do block since do blocks are just syntactic sugar. The only possible thing that might be needed by the do block is to define what monad the action should be evaluated in. Perhaps the rule could be that if (- a) occurs in some expression the compiler should search for the nearest enclosing do block to identify which monad (a) should be evaluated in, then should again search outwards from the expression (- a) to find the nearest enclosing expression (mexp) which yields a result in that same monad, then desugar to (a = \ra - mexp') where mexp' is obtained from mexp by replacing that occurrence of (- a) by (ra). (Evaluations would be done in the same order as depth first traversal of their occurrences in mexp) Regarding objections by others about (- a) being confused with a section, (-) is not a valid operator therefore it can't be part of a section so no confusion should arise imho... Best regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Using Haskell to investigate ML's value restriction
Hi, Ii is interesting that in ML, the presence of mutable ref cells and parametric polymorphism requires the whole language to be dominated by a value restriction [1] to ensure that the type system remains sound, whereas in Haskell, because IORef's can only be created (and used) in the IO monad, no such restriction is necessary. I've often wondered why such a simple thing as using a monad has this magical effect, especially since it seems to me that the real problem lies in the fact that type variables in HMD type inference are not generalised properly due to the absence of an explicit representation of the quantifier, so I decided to try using Haskell's more modern type system to investigate further, using the IO monad together with (unsafePerformIO) and (evaluate) to simulate the execution of an ML program: {-# OPTIONS_GHC -fglasgow-exts #-} module Test where import Data.IORef import System.IO.Unsafe (unsafePerformIO) import Control.Exception (evaluate) ref v = unsafePerformIO $ newIORef v put r f = unsafePerformIO $ writeIORef r f get r = unsafePerformIO $ readIORef r -- Gives a core dump as expected test1 :: IO () test1 = do let r = ref (\x - x) evaluate (put r (\x - x + 1)) evaluate (get r True) return () (test1) is based on one of the ML examples in [1], and when executed, causes a segmentation fault. The reason seems to be the strange type that is assigned to (r): *Test let r = ref (\x - x) *Test :t r r :: forall t. IORef (t - t) *Test (To run this you need to use ghci -fglasgow-exts Test.hs to get ghci 6.6.1 to display the quantifier.) What's strange (to me) about the above typing is that the forall has moved outside the IORef constructor. In other words, although we supplied the constructor with a function which can operate on any value, we got back something which, for any value, contains a function which can operate on it. The reason afaics that (test1) goes wrong is that the let binding causes (r) to be bound to the type above, so the argument matches both forall a. Num a = a - a and Bool - Bool so the action (evaluate (get r True)) tries to apply a function which expects a number to a Bool. However if we add an explicit type to (r) to get (what I see as) the expected quantification, the type checker correctly rejects the program: test2 :: IO () test2 = do let r :: IORef (forall a. a - a) = ref (\x - x) evaluate (put r (\x - x + 1)) evaluate (get r True) return () no instance for Num a ... which might seem like a reason not quite related to our chain of thought so I also tested this using: test3 :: IO () test3 = do let r :: IORef (forall a. a - a) = ref (\x - x) evaluate (put r (\'c' - 'c')) evaluate (get r True) return () which gives couldn't match expected type `a' (a rigid variable) against inferred type `Char'. In other words, the IORef must always contain a function that works with anything - we can't just give it a more specialized function, so the program is rejected for the reasons we expect. Interestingly, even without type annotations, if we use a case instead of a let, the typechecker also rejects the program: test4 :: IO () test4 = case ref (\x - x) of r - do evaluate (put r (\'c' - 'c')) evaluate (get r True) return () this time by noting that (Bool - t) does not match (Char - Char). This illustrates (afaiu) that case does not introduce any quantification, in contrast to let hence the uninstantiated meta-tyvars of r have to unify with both its uses. In conclusion, it seems that the magic given by always having to use IORef's inside the IO monad (without unsafePerformIO of course) is due to the fact that when used this way types involving IORefs never get generalized wrongly since they're never created by a let binding. Another conclusion is that if we wanted at some point to have another new strict language with Haskell's nice type system and syntax as an alternative to the ML family, and we also wanted to have references (and continuations), then either the rule for generalizing the meta-type variables in a let binding would have to be changed or else we would still have to use monads. I'd be interested to know if the use of impredicative types would automatically solve the wierd quantification problem, since: *Test :t ref ref :: forall a. a - IORef a therefore applying this to an argument of type (forall b. b - b) should hopefully give a result of type (IORef (forall b. b - b)), thus the use of impredicative types might allow such a strict variant of Haskell to use side-effects instead of monads while still retaining type soundness... ? Best regards, Brian. [1] http://www.smlnj.org/doc/Conversion/types.html ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Proposal for allowing more use of layout to avoid parentheses and commas
Hi, Following a recent thread on the Haskell' mailing list about the nusiance of having to deal with commas in tuples (when cutting and pasting things to re-order the elements there's always a pesky comma left over in the wrong place), I've written up a proposal for a very simple syntax tweak that would allow you to use the layout rule for function arguments, tuple/list/record contents etc for some future version of Haskell at http://www.haskell.org/haskellwiki/Accessible_layout_proposal This post is not intended to spark a lot of discussion just to point out the existence of the page for anyone interested. I've also added a link to all the new proposals from http://www.haskell.org/haskellwiki/Future . (If I don't reply to any follow up posts to this thread it's not because I'm ignoring them. It will just be because I have to try to get down to actually writing more of my program in the next few weeks, and I find thinking up ideas and reading posts, books, cooking, shopping, watching dvds etc, is infinitely more diverting than the painstakingly hard work of actual coding (though of course it's great in the rare occasions when things fall into place) ... ;-)) Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Channel9 Interview: Software Composability andtheFu ture of Languages
Donald Bruce Stewart wrote: magnus: All I'm trying to say is that imperative thinking is so common outside of CS/math and we learn it so early on in life that we probably can consider it the natural thinking way. foldl (\water dish - wash water dish) soapywater dishes :: [Dishes] ^^ type error I hope they weren't expensive dishes because as each dish is washed it dissolves into the water never to be seen again! :-) Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Trouble understanding records and existential types
On Thursday, January 25, 2007 7:08 AM, John Ky wrote: On 1/25/07, Brandon S. Allbery KF8NH [EMAIL PROTECTED] wrote: I'm probably missing something, but: (a) Why not: data ANode = Branch { name :: String, description :: String, children :: [AnyNode] } | Leaf { name :: String, value :: String } -- this reuse Would I be able to this? getLeaves :: ANode - [Leaf] If not, is it the case that people generally don't bother and do this instead? getLeaves :: ANode - [ANode] As has been pointed out, Leaf is a data constructor not a type so you'd have to use [ANode]. Inspired by the problem I tried a GADT: data IsLeaf data IsBranch data ANode a where Branch :: String - String - [forall b. ANode b] - ANode IsBranch Leaf :: String - String - ANode IsLeaf getLeaves :: ANode IsBranch - [ANode IsLeaf] getLeaves (Branch _ _ ls) = leaves ls leaves :: [forall b. ANode b] - [ANode IsLeaf] leaves (l@(Leaf _ _) : ls) = l : leaves ls leaves (Branch _ _ ls : lls) = leaves ls ++ leaves lls but unfortunately the above code generates the following error by GHC6.6: Couldn't match expected type `forall b. ANode b' against inferred type `ANode a' In the pattern: Leaf _ _ In the pattern: (l@(Leaf _ _)) : ls In the definition of `leaves': leaves ((l@(Leaf _ _)) : ls) = l : (leaves ls) Just out of curiosity, does anyone know why the above code doesn't compile ie why is the inferred type for the pattern: Leaf _ _ (ANode a) and not (ANode IsLeaf)? Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Trouble understanding records and existential types
Chris Kuklewicz wrote: This is how I would write getLeaves, based on your GADT: data IsLeaf data IsBranch newtype Node = Node { getNode :: (forall c. ANode c) } data ANode :: * - * where Branch :: String - String - (ANode a,ANode b) - [Node] - ANode IsBranch Leaf :: String - String - ANode IsLeaf getLeaves :: ANode a - [ANode IsLeaf] getLeaves (Branch _ _ (l1,l2) rest) = getLeaves l1 ++ getLeaves l2 ++ concatMap (getLeaves.getNode) rest getLeaves x@(Leaf {}) = [x] Thanks Chris - that's really neat! I see it's the explicit wrapping and unwrapping of the existential that solves the typechecking problem, and the use of newtype ensures there's no run-time penalty for this. Also the wrapping of the existential allowed higher order functions to be used making the code much neater. Regarding the question of why in the original example the typechecker was trying to match (forall b.ANode b) against (ANode a) and not (ANode IsLeaf), I think the answer is probably that the typechecker first finds the MGU of the types occupying the same position in all the left hand sides first, then it tries to match this against the declared type at that position, whereas for the original example to have typechecked it would have to treat each equation separately. Anyway it's now an irrelevant point given the clarity of your solution which compiles fine, Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] basic field questions
jamin1001 wrote: Hi, I am new at Haskell and have some basic questions. So then how should this be done? What if I want to do something like data Chair = Chair {pos:: Int, color :: Int} data Table = Table {pos:: Int, color :: Int} Unfortunately you have to think up different names for all constructors and field names that are declared anywhere in the same module. A possible methodical way to do this is to prefix all names by the type name (with first letter lowercase of course) eg: data Chair = Chair {chair_pos:: Int, chair_color :: Int} data Table = Table {table_pos:: Int, table_color :: Int} The reason is that when you declare a fieldname this also introduces a top level function with the same name which returns the relevant component of the record ie in the above the following top level functions are generated by the compiler: chair_pos :: Char - Int chair_color :: Chair - Int table_pos :: Table - Int table_color :: Table - Int Also, could someone tell me why this doesn't compile in GHC: data Test = A {a::Int} | B {a::Int, b::Int} data Test2 = C {c::A} (Test2 line): Not in scope: type constructor or class 'A' (A) is a data constructor whereas you need a type here, so it should be: data Test2 = C {c :: Test} Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] IO is not a monad
Yitzchak Gale wrote: I wrote: Prelude let f .! g = ((.) $! f) $! g Prelude let f = undefined :: Int - IO Int Prelude f `seq` 42 *** Exception: Prelude.undefined Prelude ((= f) . return) `seq` 42 42 Prelude ((= f) .! return) `seq` 42 42 Duncan Coutts wrote: Perhaps I'm missing something but I don't see what's wrong. The monad laws say that (= f) . return must be identical to f. I thought it was: return x = f = f x so here the lhs is saturated, so will hit _|_ when the action is executed just as the rhs will. I think the problem you're encountering is just that the above law doesn't imply: (= f) . return = f in Haskell because the lhs is of the form \x - _|_ whereas the rhs, which should really be of the form \x - _|_, is actually _|_ already(!) so the _|_ has effectively been allowed to jump to the left of the arrow hence the inequality detected by seq. Perhaps a solution would be to force _|_ to respect the shape of the type, thus non-terminating values of type a - b would be given the value \_ - _|_ instead of _|_ ? Regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] IO is not a monad
Brian Hulley wrote: Yitzchak Gale wrote: I wrote: Prelude let f = undefined :: Int - IO Int Prelude f `seq` 42 *** Exception: Prelude.undefined Prelude ((= f) . return) `seq` 42 42 The monad laws say that (= f) . return must be identical to f. I thought it was: return x = f = f x so here the lhs is saturated, so will hit _|_ when the action is executed just as the rhs will. I think the problem you're encountering is just that the above law doesn't imply: (= f) . return = f in Haskell ok so far... because the lhs is of the form \x - _|_ No I got this wrong. Evaluating the lhs to WHNF doesn't hit the _|_. (Incidentally the version using .! evaluates to exactly the same thing since (= f) `seq` ((= f) . return) = ((= f) . return) since (\x - x = f) is already in WHNF afaiu) Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] IO is not a monad
Brian Hulley wrote: Brian Hulley wrote: Yitzchak Gale wrote: I wrote: Prelude let f = undefined :: Int - IO Int Prelude f `seq` 42 *** Exception: Prelude.undefined Prelude ((= f) . return) `seq` 42 42 The monad laws say that (= f) . return must be identical to f. I thought it was: return x = f = f x so here the lhs is saturated, so will hit _|_ when the action is executed just as the rhs will. Ooops! But that does not mean the equation holds because for example Prelude (return 3 = f) `seq` 42 42 Prelude (f 3) `seq` 42 *** Exception: Prelude.undefined In the lhs you only hit _|_ when the composite (=) action is actually being executed whereas in the rhs you hit _|_ when computing the function which will return the action to execute so there is difference. Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Article review: Category Theory
Lennart Augustsson wrote: On Jan 19, 2007, at 08:05 , [EMAIL PROTECTED] wrote: Thus, Hask is not a category, at least not as defined in the article. The problem is that (either) morphisms or the morphism composition ('.') are not internalized correctly in Haskell. And this is why some of us think that adding polymorphic seq to Haskell was a mistake. :( I've often wondered why seq is the primitive and not $! Would this solve the problem? Is there any solution that would allow excess laziness to be removed from a Haskell program such that Hask would be a category? Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] seq (was: Article review: Category Theory)
Neil Mitchell wrote: Hi Brian, Is there any solution that would allow excess laziness to be removed from a Haskell program such that Hask would be a category? class Seq a where seq :: a - b - b Then you have a different seq based on the types, and it doesn't go wrong. You would probably want deriving Seq support. This seems an amazingly neat solution to a really terrible problem, so: 1) Does anyone know why this was not used in the first place? 2) Would it be good to use this in future versions of Haskell? 3) Is there any practical program which requires the current seq that could not be rewritten to use the typeclass seq? Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Article review: Category Theory
Johan Gršnqvist wrote: Ulf Norell skrev: On Jan 16, 2007, at 7:22 PM, David House wrote: In the section on the category laws you say that the identity morphism should satisfy f . idA = idB . f This is not strong enough. You need f . idA = f = idB . f (I do not know category theory, but try to learn from the tutorial/article/introduction.) Given this, and looking at the figure accompanying exercise 2. Can I not then show that f=h from: f.g = idA (f.g is A - A and idA is the only morphism A - A, closedness gives the equality) h.g = idA (same argument) g.f = g.h = idB (same argument) thus (using the laws for id and associativity) f = idA . f = (h . g) . f = h . (g . f) = h . idB = h Thus in the figure f=h must hold, nad one arrow can be removed from the graph. But f /= h so by the above reasoning you get a proof by contradiction that the figure is not a category. Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Article review: Category Theory
David House wrote: http://en.wikibooks.org/wiki/Haskell/Category_theory I'd love comments from newcomers and experts alike regarding my approach, the content, improvements and so on. Of course, it's on the wikibook, so if you have anything to add (that's not _too_ substantial otherwise I'd recommend discussion first) then go ahead. Hi David, In the introduction you say that Set is the category of all sets with morphisms as standard functions and composition as standard function composition. But in the second exercise in the intro it's clear that function composition is not associative. Therefore surely this means everything based on function composition can't be a category? Also, why does this exercise contain redundant morphisms (I hope I'm not spoiling it for anyone by saying this or perhaps I've just totally misunderstood everything)? Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Article review: Category Theory
Brian Hulley wrote: David House wrote: http://en.wikibooks.org/wiki/Haskell/Category_theory But in the second exercise in the intro it's clear that function composition is not associative. Apologies. I got totally confused with the way function composition is back to front etc. I still have no idea what the solution to the second exercise is though. Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Article review: Category Theory
Yitzchak Gale wrote: David House wrote: I've added a bit more explanation, so it may now be palatable. It is quite a hard exercise, though, perhaps it shouldn't come so early on. In my opinion, it is now much more clear. And it is a very instructive example. If people still find it too hard, you could add the additional hint: Keep in mind that there are no morphisms other than the ones shown in the diagram. Ok I understand it now, because David has just clarified offlist the thing that puzzled me about the diagram: namely that morphisms have an individuality of their own that isn't fully determined by the lhs and rhs of the arrow like the relationship between a function and its type. Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Redefining superclass default methods in a subclass
Meng Wang wrote: Hi Brian, Thank you for starting the thread. We (Martin Sulzmann and me) proposed a type class extension which allows modular extension of superclasses (a complement of subclass extension). The idea has been shown to be particularly useful in (but not limited to) encodings of generic programming with type classes. A brief introduction of the proposal is documented in our wiki: http://taichi.ddns.comp.nus.edu.sg/taichiwiki/GPHomePage. I will try to add it as a link in yours soon. A more detailed and formal description of the proposal can be found in our Workshop on Generic Programming 06 paper which is available at http://www.comp.nus.edu.sg/~sulzmann http://web.comlab.ox.ac.uk/oucl/work/meng.wang/ Thanks - I've added the above links to http://www.haskell.org/haskellwiki/Class_system_extension_proposal along with a one-line summary which I'm sure is totally imperfect but hopefully not too misleading ;-) Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Redefining superclass default methods in a subclass
Simon Peyton-Jones wrote: One of the great things about John's class-alias proposal is that John worked out a lot of details and captured them in a web page, rather than it getting buried in an email thread. If you have ideas to refine his proposal, it'd be good to see if, with him, you can come up with a unified design, and again capture it in a Wiki page or something. I've started a page at http://www.haskell.org/haskellwiki/Class_system_extension_proposal John - I haven't added anything about your class alias proposal because you've copyrighted your proposal and I don't want to do the wrong thing ;-) Can you add a section for your proposal (or containing a link to your proposal) on his page? Please could everyone who has any other ideas about class system extensions add them to the page above so that we have a central location. Hopefully it will gradually become clear what all the issues are and perhaps a path for trying to implement some extensions in order of difficulty. Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Redefining superclass default methods in a subclass
Brian Hulley wrote: Simon Peyton-Jones wrote: One of the great things about John's class-alias proposal is that John worked out a lot of details and captured them in a web page, rather than it getting buried in an email thread. If you have ideas to refine his proposal, it'd be good to see if, with him, you can come up with a unified design, and again capture it in a Wiki page or something. I've started a page at http://www.haskell.org/haskellwiki/Class_system_extension_proposal John - I haven't added anything about your class alias proposal because you've copyrighted your proposal and I don't want to do the wrong thing ;-) Can you add a section for your proposal (or containing a link to your proposal) on his page? ^^^ Apologies for typo - should be this page Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] why can't you surround (+) in backticks and have it beinfix?
[EMAIL PROTECTED] wrote: David House wrote: You can fake this: (-!) = ($) (!-) = flip ($) foo -! liftM2 (,) !- bar Was anyone in that brainstorm thinking of Chung-chieh Shan's -: and :- (http://www.haskell.org/pipermail/haskell-cafe/2002-July/003215.html) or was the similarity just a really cool coincidence? I hope no-one seriously thinks the above syntax is clearer than: liftM2 (,) foo bar Brian. -- Operators: one small step for compilers, one giant leap for obfuscation. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Why does the wiki search facility not work properly?
Hi, There is a page on the Haskell Wiki titled Talk:SantaClausProblem subtitled Beautiful concurrency. However typing any of the following into the search box *doesn't* lead to the page: Santa talk:santaclausproblem beautiful beautiful concurrency Talk:Santa In fact to get the page you have to type the *exact* full title in the *exact* case. Luckily I could always refer back to SimonPJ's post to the Haskell mailing list to find the link to the page, but I think this situation is really bad because it means that things on the wiki are more or less just being thrown down a gaping void never to be seen again unless you know which catagories to look in from the main page. Another point is that the word beautiful does occur on the page but the page is not included in the list of page text matches. Perhaps the site is not being automatically re-indexed frequently enough? There is also a bunch of check boxes at the bottom of the search results page that doesn't seem to do anything either except cause nothing at all to happen when you click search unless the (Main) box is the only box ticked. Anyway I thought I'd just point this out in case anyone knows how to fix it. Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Redefining superclass default methods in a subclass
Bulat Ziganshin wrote: Hello Brian, Thursday, January 4, 2007, 10:00:05 PM, you wrote: deeper, the programmer is burdened more and more by the need to cut-and-paste method definitions between instances because Haskell doesn't allow a superclass (or ancestor class) method default to be redefined in a subclass. i've runned into this problem with Streams library. finally i've decided to wrote bodies of such methods outside of class: [example snipped] Hello Bulat, Thanks for the workaround, which solves the need to copy and paste method bodies though not the problem of having to write out instance decls for a potentially large chain of classes leading to the subclass of interest. Part of the motivation for proposing that a superclass method default could be redefined in a subclass (or a particular instance) is that it would allow some refactorings of the class hierarchy without affecting code that just uses the subclass - in particular it would allow existing code using Monad to compile unchanged even when Monad moved down to Functor = Applicative = Monad because return and = are enough to get completely defined instances for Functor and Applicative. Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Stupid newbie question
Brian Hurt wrote: nth 0 (x:xs) = Some x nth i (x:xs) = if i 0 then Empty else nth (i-1) xs nth i [] = Empty [blows stack on large i] As other people have pointed out, this is due to laziness. I'd write it like: nth 0 (x:_) = Some x nth i (_:xs) = of i 0 then Empty else (nth $! i-1) xs nth _ [] = Empty where a general rule of thumb is always to replace (fun intexp) by (fun $! intexp) whenever intexp is just a trivial arithmetic expression that doesn't involve traversing (ie forcing of) any other data structure. Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Stupid newbie question
Brian Hulley wrote: Brian Hurt wrote: nth 0 (x:xs) = Some x nth i (x:xs) = if i 0 then Empty else nth (i-1) xs nth i [] = Empty [blows stack on large i] As other people have pointed out, this is due to laziness. I'd write it like: nth 0 (x:_) = Some x nth i (_:xs) = of i 0 then Empty else (nth $! i-1) xs ^^^ -- oops! nth _ [] = Empty I think the above code would be more efficient written as: nth n xs = if n 0 then Empty else nth' n xs where nth' 0 (x:_) = Some x nth' i (_:xs) = (nth' $! i - 1) xs nth' _ _ = Empty since the first 2 cases deal with every situation where we've got a non-empty list and an index = 0 (so no need to keep checking that the index is = 0 in the second case - instead the test can be moved outside the loop) and there's no need to pattern match against [] in the last case because we already know this must be an empty list. (Though in general it's probably a good idea to make each pattern as independent as possible when writing a function so that if some cases of a function are later edited there's more chance of the compiler being able to lead you to errors via the incomplete patterns warning - hopefully the compiler can optimize out any redundant checks) Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Stupid newbie question
Brian Hulley wrote: Brian Hulley wrote: Brian Hurt wrote: nth 0 (x:xs) = Some x nth i (x:xs) = if i 0 then Empty else nth (i-1) xs nth i [] = Empty [blows stack on large i] As other people have pointed out, this is due to laziness. I'd write it like: nth 0 (x:_) = Some x nth i (_:xs) = of i 0 then Empty else (nth $! i-1) xs ^^^ -- oops! nth _ [] = Empty Actually I see I should have read Jeremy Shaw's answer more carefully before giving my own since I'd missed the point about the problem being with the list itself not the decrementing of (i) (which wouldn't be a problem since it is immediately forced on the next iteration by the comparison of i to 0). The answer therefore lies in the laziness of the makelist function which could be solved by: makelist i = i : (makelist $! i - 1) Jeremy Shaw wrote: pps. I didn't explain why [1..100] works, but [1..] fails, because I don't know :) It's a bit suprising to me... I think this might be because the code that produces the list [1..100] would have to be something like: produce n i = if i n then i : produce n (i +1) else [] so each element of the list is now forced by the comparison with n, so even though the end of the list will be a thunk when 100 has not yet been reached, none of the elements are thunks. Anyway it was certainly not a stupid question - thanks for asking it. Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Redefining superclass default methods in a subclass
Hi, Looking at some of the ideas in http://www.haskell.org/haskellwiki/The_Other_Prelude , it struck me that the class system at the moment suffers from the problem that as hierarchies get deeper, the programmer is burdened more and more by the need to cut-and-paste method definitions between instances because Haskell doesn't allow a superclass (or ancestor class) method default to be redefined in a subclass. For example, consider this part of a proposal for Functor = Applicative = Monad: -- I've just used 'm' so it's easy to see what parts are relevant to Monad class Functor m where fmap :: (a - b) - m a - m b class Functor m = Applicative m where return :: a - m a (*) :: m (a - b) - m a - m b () :: m a - m b - m b ma mb = -- left as exercise for a rainy day! class Applicative m = Monad m where (=) :: m a - (a - m b) - m b The problem with this is that whereas someone defining a Monad at the moment only needs to define (return) and (=), with the above, though it gives obvious advantages in flexibility, generality etc, defining a new Monad involves providing methods (in instance decls) for fmap and (*) as well, and the default method for () is ma mb = (fmap (const id) ma) * mb (from that page above) which I'm sure everyone will agree is a *lot* more complicated than: ma mb = ma = (\_ - mb) Not only is the first definition for () more complicated, it obscures the simple fact that for monads it's just a trivial special-use case of = where the bound argument is ignored. Therefore I'm wondering if it would be possible to allow default methods for a superclass to be defined, or redefined, in a subclass, so we could write: class Applicative m = Monad m where (=) :: m a - (a - m b) - m b mf * ma = mf = \f - ma = \a - return (f a) ma mb = ma = \_ = - mb fmap f ma = ma = \a - return (f a) (I know the above can be written in a more point-free style but I wrote it like that to make it easy to understand what's happening.) The essential point here (excuse the pun :-) ) is that it is impossible to write the default methods in the class in which the operation is defined, because the implementation depends on methods of the relevant subclass (and will therefore be different for different subclasses though not for each particular instance of a given ancestor class of a particular subclass). As Haskell stands at the moment, we are forced to cut and paste identical methods for each individual instance of each ancestor class of a particular subclass because we can't override an ancestor class method in the *class* decl for a subclass. The type class system at present is based on the idea that you can define related methods together and in terms of each other, at one level of the hierarchy. However as the above example shows, related methods sometimes need to be spread over the hierarchy but we still want to be able to define default implementations of them in terms of each other. Perhaps there is some reason this can't be done? Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Redefining superclass default methods in a subclass
Roberto Zunino wrote: Brian Hulley wrote: because Haskell doesn't allow a superclass (or ancestor class) method default to be redefined in a subclass. How one would write instances? Using your Monad class, does instance Monad F where return = ... (=) = ... automatically define an instance for Applicative? Yes, but I'd make the method names be call-site-bound so the actual method that is called is determined by the set of instance decls and class decls visible at each particular call site, and any instances that are automatically created would be hidden by any explicitly defined instances that are visible. If it does: What if there already is such an instance? Which one gets used for ()? The user-defined one or the Monad default? A possible proposal could be: 1) Class and instance decls would allow method implementations to be given for any methods in the class or any ancestor class. 2) Whenever an instance decl is visible there would always be a full set of instance decls for all ancestor classes, by supplementing the set of explicitly given instance decls that are visible by automatically generated implicit instance decls. 3) The most specific method implementation would always be chosen (ie prefer an explicit instance method over a class method and prefer a subclass method to a superclass method) In particular rule 2) would mean that the actual method used depends on what's available at the call site which means that a Haskell program could no longer be thought of as being re-written into a single module before compilation, since the meaning of overloaded names would be determined by (CalledFromModule, Type) not just Type. (The desire to hide instance decls or have different instance decls for the same type within the same program has come up before on the list but unfortunately I can't remember who posted something along these lines or when.) Is separate compilation still possible? (If there is no instance right now, one might pop out in another module...) I think it should still be possible because within a module, the overloadings would be determined by the set of explicitly defined instances in scope in that module. Various optimizations might be more tricky because the call site module associated with each overloaded name would need to be taken into account when inlining across module boundaries (ie a name used inside an inlined function needs to be resolved as if it had been used in the module where the function was defined not the module where the function is inlined). For example: module A where import Proposed.Control.Monad data T a = T a instance Monad T [-# INLINE foo #-} foo :: a - T a foo = return -- uses Monad class default -- which is inherited from the Applicative -- class default module B where import A import Proposed.Control.Monad instance Applicative T where return x = retB x bar :: T a bar = return 'q'-- would use (retB) zap :: T a zap = foo 'q'-- would use (return) from A A question is whether the extra difficulty in resolving overloadings (for human reader as well as complier) is worth the advantages of being able to get generated definitions for () for Applicative and (fmap) for Functor from a single instance decl for (Monad.=) etc. [Rearranged] The class aliases proposal lists several similar shortcomings of the current class system. http://repetae.net/john/recent/out/classalias.html IIUC the class alias proposal is about being able to group classes together and deal with them as a whole so similar issues of resolving overloadings arising from overlapping aliases/ explicit instance decls etc would arise (and I imagine the solutions would lie in similar directions). Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Composing functions with runST
Yitzchak Gale wrote: Can anyone explain the following behavior (GHCi 6.6): Prelude Control.Monad.ST runST (return 42) 42 Prelude Control.Monad.ST (runST . return) 42 interactive:1:9: Couldn't match expected type `forall s. ST s a' against inferred type `m a1' In the second argument of `(.)', namely `return' In the expression: (runST . return) 42 In the definition of `it': it = (runST . return) 42 Section 7.4.8 of GHC manual states that a type variable can't be instantiated with a forall type, though it doesn't give any explanation why. Hazarding a guess, I suggest it *might* be due to the fact that forall s. ST s a means forall s. (ST s a) whereas you'd need it to mean (forall s. ST s) a in order for it to unify with (m a). Just a guess - I'd be interested to know the real reason as well. Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Idiomatic Haskell equivalent of keyword argumentsto functions
Paul Moore wrote: I'm thinking around the design of a couple of things, and am hitting an issue which I know how I would solve in Python, but I'm not sure what a good idiomatic Haskell approach would be. The problem is that I am trying to write a function which takes a rather large number of arguments, many of which are optional (ie, have sensible defaults). There's an interesting solution to this in section 15 (starting page 53) of Magnus Carlsson and Thomas Hallgren's Fudgets thesis available online at: http://www.cs.chalmers.se/~hallgren/Thesis/ (Fudgets main page is at http://www.cs.chalmers.se/ComputingScience/Research/Functional/Fudgets/ ). Basically the idea is that for any function which takes lots of params, the params are gathered together into a datatype whose details are hidden from the user of the function. For each parameter, the user is given a function called a Customiser in the thesis, which takes a value of the hidden datatype and modifies it by setting the relevant parameter. Multiple params can therefore be specified by chaining Customisers together in any order with the usual function composition. The original function, instead of taking lots of params, now just takes a single parameter: a Customiser, which is used to turn the default params into the customised params. This is similar to the idea of using records but has the advantage that by judicious use of typeclasses of which the param data is an instance, you don't need to keep on inventing different names for the same thing (eg to specify colour for the background of a label control in a GUI or colour for a font you could use the name setColour in both cases). (A possible disadvantage is the overhead of having to create a whole new modified version of the parameter record for each Customiser in the composition so if efficiency were an issue you'd have to see if the compiler could inline the composition of the customiser functions to make it as efficient as the built in multiple field record update using rec{a=a', c=c'} syntax) To make things concrete, the example I'm really thinking of is a send an email function, which would take a subject, a body, a list of recipients, optional lists of cc and bcc recipients, an optional mailserver (default localhost), an optional port (default 25), and possibly optional authentication details. I found a couple of Haskell modules implementing a SMTP client, but they both just used a list of positional parameters, which I'm not really happy with. At the very least, I'd like to wrap them in a nicer interface for my code. -- hidden from clients data EmailParams = EmailParams { subject :: String , body :: String , recipients :: [Recipient] , cc :: [Recipient] , bcc :: [Recipient] , mailserver :: Mailserver , port :: Port , authentication :: Authentication } -- record syntax elided to save space defaultEmailParams = EmailParams [] [] [] defaultMailserver defaultPort defaultAuthentication --a Customiser visible to clients setSubject :: String - EmailParams - EmailParams setSubject s ep = ep{subject = s} -- etc send :: (EmailParams - EmailParams) - IO () send f = sendInternal (f defaultEmailParams) where sendInternal :: EmailParams - IO () sendInternal = ... -- In user code: main = send (setSubject Test . setBody A test email) Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Seeking advice on a style question
Steve Schafer wrote: In my text/graphics formatting work, I find myself doing a lot of pipeline processing, where a data structure will undergo a number of step-by-step transformations from input to output. For example, I have a function that looks like this (the names have been changed to protect the innocent--and to focus on the structure): process :: a - b - c - d - e process x1 x2 x3 x4 = let y01 = f01 x1 x2 x3; y02 = f02 x1; y03 = f03 y02; y04 = f04 y03; y05 = f05 x1 y01 y04; y06 = f06 x2 y05; (y07,y08) = f07 y01 y06; y09 = f08 y07; (y10,y11) = f09 x2 x4 y09 y08; y12 = f10 y10; y13 = f11 y12; y14 = f12 x1 x2 x3 y01 y13; y15 = f13 y14; y16 = f14 y15 y11 in y16 Disclaimer: just re-written by hand so needs double-checking before use: process x1 x2 x3 x4 = let y01 = f01 x1 x2 x3 (y07, y08) = f07 y01 (f06 x2 (f05 x1 y01 (f04 (f03 y02 (y10, y11) = f09 x2 x4 (f08 y07) y08 in f14 (f13 (f12 x1 x2 x3 y01 (f11 (f10 y10 y11 You can also make it look more like the diagram by using more indentation eg: process x1 x2 x3 x4 = let y01 = f01 x1 x2 x3 (y07, y08) = f07 y01 (f06 x2 (f05 x1 y01 (f04 (f03 y02 ... Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Versioning
Lennart Augustsson wrote: On Dec 21, 2006, at 15:53 , Neil Mitchell wrote: Hi there are really no choices for real development. many libraries, language extensions and techniques are for ghc only I develop everything in Hugs, including the Yhc compiler itself. Hugs is great. There are lots of extensions in GHC, but Haskell 98 is a perfectly useable language! I must second this opinion. There's this (false) perception that you need all kinds of extensions to make Haskell usable. It's simply not true. Certain extensions can make your life easier, but that's it. Well, FingerTrees for example, require MPTCs as in pushL :: Measured v a = a - FingerTree v a - FingerTree v a For any kind of object oriented programming you need existentials to separate the interface from the different concrete objects. Also in the code I've written I've often needed higher rank polymorphism and scoped type variables. Sure it's possible to use all kinds of horrific hacks to try and avoid the need for scoped type variables etc but why would anyone waste their time writing difficult obfuscated code when GHC has the perfect solution all ready to use. In other words, what on earth is good about gluing oneself to Haskell98? Life's moved on... Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Versioning
Neil Mitchell wrote: Hi In other words, what on earth is good about gluing oneself to Haskell98? Life's moved on... If you stick to Haskell 98 you can: * Convert your code to Clean (Hacle) * Debug it (Hat) * Run it in your browser (ycr2js) * Document it (Haddock) * Make a cross platform binary (yhc) * Get automatic suggestions (Dr Haskell) ... Sometimes you need a type extension, but if you don't, you do get benefits. True, though it would be even better if the usual extensions were more widely supported, though I suppose identifying what's useful and therefore worth supporting is the point of the Haskell Prime process. As an aside I've often thought it would be better if the various components of Haskell compilers/tools would be separated out so that people could effectively build their own compiler tailored more specifically for their needs. Ie lots of smaller projects each dealing with a particular phase of Haskell processing which would be joined together by standard APIs, so that someone could use the latest type system extensions with whole program optimization while someone else could use those same type extensions with a back end designed for graphical debugging etc, and also so that people just interested in developing whole program optimization (for example) wouldn't have to reinvent the ever-more-difficult wheel of lexing/parsing/typechecking/targeting multiple platforms... Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Stronger static types, was Re: [Haskell-cafe] Re: Versioning
Jacques Carette wrote: Yes, dependent types have a lot to do with all this. And I am an eager lurker of all this Epigram. Would it be possible to augment Haskell's type system so that it was the same as that used in Epigram? Epigram itself uses a novel 2d layout and a novel way of writing programs (by creating a proof interactively) but these seem orthogonal to the actual type system itself. Also, typing is not the only issue for compile time guarantees. Consider: data Dir = Left | Right | Up | Down deriving Eq -- Compiler can check the function is total foo :: Dir - String foo Left = Horizontal foo Right = Horizontal foo Up = Vertical foo Down = Vertical versus -- Less verbose but compiler can't look inside guards foo x | x == Left || x == Right = Horizontal foo x | x == Up || x == Down = Vertical versus something like: foo (Left || Right) = ... foo (Up || Down) = ... Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Shrinking the Prelude: The categorical approach
Imam Tashdid ul Alam wrote: hi guys, I was just wondering if anyone is interested is a quasi-project of rewriting the Prelude (only shrinking it as measured by the total number of names imported, read along...) the idea is (just to be substantially different in approach) to develop an alternate history of Haskell. take map for example, and fmap, I don't think they should be named different (fmap is ugly, not suggestive, and conceptually the same). mplus could be renamed (++) (they are conceptually the same I suggest that all functions in classes be given actual names and ASCII symbolic names could be defined outside the class as an additional convenience eg: class Monad m = MonadPlus m where mzero :: m a mplus :: m a - m a - m a (++) = mplus-- 'convenience' name I think people forget that ASCII symbol names which look intuitive to them when they are writing a library or paper, can be very confusing for people who need to use many libraries (with consequent explosion of obfuscatory symbols) in a project, look terrible when qualified, and make code difficult to read because of the need to find/remember precedences and associativity. (Note that Haddock does *not* supply this info, you need to look at the actual source code of the library to find it out.) , mzero looks odd, name it empty, or simply zero) What about (mempty) from Monoid or (empty) from Data.Sequence or Control.Applicative? Either these are in some way the same thing as mzero, or else they are different in which case either qualified imports would be needed everywhere (not necessarily a bad thing) or different names like the ones we already have, are needed. although I think concat should be replaced by msum (or the other way around preferably :) ? msum is a bad name) I am somewhat confused by join. concat seems to match join's type but I don't think the ideas coincide. and so on. in particular, we would want: * no backwards compatibility. the Prelude as is it, is good enough. we are defining a new module. Starting with a clean slate seems a good idea, especially to get rid of lispy names like (cons), (snoc), (null) and replace them with something self-explanatory like (pushL), (pushR), (isEmpty). * clean categorical hierarchy of type classes (category theorists wanted!) promoting uniformity. This would be great. However it is a question to me whether it is even possible to organize everything in a single hierarchy. Eg look at the problems with trying to reorganize Num, or standard OOP problems with hierarchies in general. Since there are multiple ways of looking at a domain, it is likely there will need to be multiple hierarchies which will probably not interact so well. * cleaner names. foldl1 means nothing. absolutely nothing. what's the 1 for? A while back I suggested using capital letters for suffix to distinguish the functionality (fold) from the variant (L == left). Perhaps (foldl1) could be renamed (foldLN) ie fold + left + non-empty or (foldLO) for fold + left + occupied. * our Prelude only contains typeclasses, datatypes, and functions of utmost conceptual (and semantic, such as error, undefined and seq) importance, everything else goes to other modules. our Prelude is not going to be a place for convenient declarations. * the suffix method of naming (liftM2) is considered messy. we would prefer a seperate module (promoting qualified import). In the particular case of *M functions, I quite like the existing naming since it's clear that it's a monadic function. However I'd agree that names like (newIORef) are an abomination, that should be replaced by (Ref.new). this is a fun project. we will not rewrite the Prelude, we'll merely rename it. I would suggest the name TheOtherPrelude to make our intentions clear. the conveniences (like concatMap) goes to TheOtherPrelude.Extension. I suggest we do it on the wiki. anyone interested just open a page with your name of choice. I am not doing it only because there's no point doing it if no one's interested. Good luck with this. For my own project, I re-implemented FingerTree's so I could use my preferred naming style (and also as an exercise following the excellent tutorial-style FingerTree paper), and wrote some trivial wrappers for a few other modules eg Data.IORef, Data.Unique so that I could use Ref.new, Unique.new etc.I think it would be quite a big task to refactor the entire code base according to a clean hierarchy of type classes, and also a task I can't really help with since I'm not familiar enough with category theory at present, but certainly it would be a worthwhile endeavour imho, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell Side Effect
Ashley Yakeley wrote: Since learning Haskell, I can now count in Spanish! See: one in Spanish, two in Spanish, three in Spanish, four in Spanish.. Is there a solution ie some concept C such that C Haskell C Spanish, somewhere? Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Class annotation on datatype ineffective in function
Reto Kramer wrote: The code below does not compile unless the bar function is annotated with a suitable constraint on the class of the formal parameter. class (C a) data (C foo) = XY foo = X foo | Y foo bar :: a - XY a bar aFoo = X aFoo As suggested, this works: bar :: (C a) = a - XY a Can someone explain to me why the compiler can not infer that a (in bar) must be (C a) from the bar result type XY a (by way of the C class provided for the datatype)? Hi Reto - If you'd not given any signature at all the compiler would have inferred the correct type for bar, but since you gave an explicit signature, the compiler had no option but to complain that you missed out the C a constraint. (ie if you decide to provide a signature you must give the full signature including constraints since the compiler won't add anything to them - partial signatures are not (yet) supported) Regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Showing the 1 element tuple
Neil Mitchell wrote: Hi, A weird question, what does the 1 element tuple look like? () -- 0 element tuple (,) a b -- 2 element tuple (,,) a b c -- 3 element tuple () a - meaningless (a) - a in brackets GHC has the 1 element unboxed tuple, (# a #), and all the other sizes unboxed as well, but how would you visually represent the 1 element boxed tuple? Tuples represent dimensionality therefore a 1-element tuple is just a 1-dimensional value ie the value itself hence a == (a) == ((a)) == (((a))) == ... Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [Haskell] ANNOUNCE: Phooey -- a Functional UI library for Haskell
Brian Hulley wrote: Conal Elliott wrote: GUIs are usually programmed in an unnatural style, in that ... Also, suppose you have a gui consisting of an edit widget such that when the user types something it gets lexed, parsed, and fontified as a Haskell program, ie from the user's point of view the widget maintains a syntax highlighted view of the code which is continuously updated. Would your system do the lexing/parsing for every key that was pressed or only once, when the widget needs to be re-rendered (a typical gui for Windows would only propagate changes and re-draw the gui (ie lex/parse/fontify) when there are no event messages pending)? Thinking about this more, a better example would be a gui with 2 widgets: an edit widget to type in code and a list widget which displays a list of top level functions defined in that code. (The code could be Haskell or some simple toy language.) Then the question becomes: how to set things up such that the code in the edit widget is only parsed when the list widget (and/or edit widget) is asked to render it's contents rather than every time the user presses a key. I think perhaps the problem would be solved by the edit widget passing a lazy parse tree (ie an expression evaluating to the parse tree) to the list widget. But an interesting thing is if you compare this to imperative guis, in the functional gui each widget passes lazy expressions eagerly whereas in imperative guis each widget passes eagerly evaluated expressions lazily ie functional is push messages whereas imperative is pull changes when I'm asked to pick or render something etc and I'm dirty. (Have I got this wrong?) I imagine that the overhead of eager passing in the functional gui is a small price to pay for the ease of using a functional gui, since the important thing is that in both guis, the hard work of parsing the code in the edit buffer would only be done on demand, unless I'm much mistaken. If you're still thinking of examples for your paper it would also be really great to see how you'd create a widget that displays the result of another process (eg a window that displays the output as ghc compiles a program) or some other example of how to use the IO monad inside a widget for those unfamiliar with combining arrows with monads. It would also be useful to know more about the relationship between the functional gui and WxWidgets to see what characteristics an imperative gui toolkit must have in order to be usable with it. (Like the extremely useful discussion of low level details in the Fudgets thesis.) Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Aim Of Haskell
Kirsten Chevalier wrote: since it's not as if anyone programs in Pascal anymore. Yet I'm sure most people who did a computer science degree some decades ago remember the old joke about passing things by name or value for what it's Wirth... :-) Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Functional GUI combinators for arbitrary graphs of components?
Taral wrote: On 12/1/06, Brian Hulley [EMAIL PROTECTED] wrote: This problem is so general (ie converting a cyclic graph into an expression tree such that each node appears no more than once) that I'm sure someone somewhere must already have determined whether or not there can be a solution, though I don't know where to look or what to search for. I suggest you check the Functional Graph Library (FGL). It's shipped as part of GHC. Thanks for the suggestion. FGL itself (afaics) doesn't seem to have what I was looking for but graph algorithm would be a good place to start looking. Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Functional GUI combinators for arbitrary graphs ofcomponents?
Paul Hudak wrote: Brian Hulley wrote: Anyway to get to my point, though all this sounds great, I'm wondering how to construct an arbitrary graph of Fudgets just from a fixed set of combinators, such that each Fudget (node in the graph) is only mentioned once in the expression. To simplify the question, If you consider just Dags, I believe that this question is equivalent to asking what set of combinators will allow you to create an arbitrary composition of functions that allow sharing inputs and returning multiple results. And I think that one answer to that is the set of combinators that make up the Arrow class. If you want to include recursion (i.e. cycles), then you'd have to throw in ArrowLoop (although that might only provide a nested form of cycles). It's in this sense that Fudgets is analogous to Fruit. Thanks. Actually thinking more about it I've probably missed the point that for a compositional GUI there's no need for a general graph, since each view/controller of the underlying model could be encapsulated as a single widget (eg fudget or signal transformer) which could be connected to the model via a loop which exposes only the model (thus allowing other views to be added later). Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Strange type behavior in GHCi 6.4.2
Grady Lemoine wrote: f x = x^3 f' = snd . (evalDeriv f) When I load this in GHCi, I get: *Main :t f f :: (Num a) = a - a *Main :t snd . (evalDeriv f) snd . (evalDeriv f) :: (Num a, Num (Dual a)) = a - a *Main :t f' f' :: Integer - Integer Why is the type of f' Integer - Integer, especially when the type of the expression it's defined as is more general? Is this something I'm not understanding about Haskell, or is it more to do with GHC 6.4.2 specifically? This is the monomorphism restriction, which basically says that any binding which just has a single variable on the left of the '=' is artificially forced to be monomorphic (unless you've given it an explicit type signature) eg: f = \x - x + 1-- Integer - Integer whereas f x = x + 1-- Num a = a - a The reason for this is that if you have something like: let x = e in (x,x) you often expect the expression (e) to be evaluated at most once, and shared by the two components of the tuple. However if there were no monomorphism restriction, then (x) could be polymorphic hence (e) would have to be evaluated twice (once for each overloading, even if the result tuple is fed to another function which expects both elements to have the same type) which would make programs run slower than the programmer expected. I couldn't find any page on the wiki about this, but there's lots of stuff scattered around on the web, and endless discussions in the Haskell mailing lists which make entertaining reading ;-) (The MR is controversial - see http://hackage.haskell.org/trac/haskell-prime/wiki/MonomorphismRestriction for the latest on what might happen to it in future versions of Haskell.) Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Functional GUI combinators for arbitrary graphs of components?
Hi, I've been looking at the Fudgets research (http://www.cs.chalmers.se/ComputingScience/Research/Functional/Fudgets/ ) as an example of a purely functional gui. Afaiu a brief summary is that a Fudget can represent a GUI widget or some other object, which can have some internal state, and which receives and passes messages to the other Fudgets it is connected to. Fudgets are connected to each other by combinators eg: second == first-- sequential (first sends messages to second) a * b -- parallel There is a continuation passing implementation such that the messages are passed and internal states of Fudgets are updated (by replacing each fudget with an updated fudget) as these expressions are evaluated hence the message passing and maintenance of state doesn't involve any IORefs though interaction with external devices such as the OS uses IO. Anyway to get to my point, though all this sounds great, I'm wondering how to construct an arbitrary graph of Fudgets just from a fixed set of combinators, such that each Fudget (node in the graph) is only mentioned once in the expression. To simplify the question, assume we have the following data structure to describe the desired graph: data LinkDesc a = Series a a | Broadcast a [a] | Merge [a] a type GraphDesc a = [LinkDesc a] and a function to compute a combined object (eg Fudget) corresponding to an arbitrary graph would be: mkObj :: Ord label = Map label Obj - GraphDesc label - Obj mkObj = -- ??? The result of mkObj will be some expression, composed from a finite set of combinators applied to the named objects, but with the all important property that each named object appears no more than once in the expression (this is what allows Fudgets to correspond to notional objects which maintain internal state - during evaluation each fudget gets replaced by an updated fudget hence can only appear once in the whole expression). As a very simple example using existing Fudgets combinators, type Map label value = [(label, value)] mkObj [(A, objA), (B, objB), (C, objC)] [Series A B, Series B C] ===objC == objB == objA and mkObj [(A, objA), (B, objB), (C, objC)] [Broadcast A [B, C]] === (objB * objC) == objA However: mkObj [(A, objA), (B, objB), (C, objC), (D, objD)] [Broadcast A [B, C], Series B D, Series A D] === ??? The Fudgets library provides many combinators eg for looping, but even so, I don't think there are sufficient combinators to express the above graph (though possibly extra nodes and tagging/untagging would solve this example), or more heavily connected graphs such as: [Series A B, Series B C, Series C D, Series D B, Series C A] This problem is so general (ie converting a cyclic graph into an expression tree such that each node appears no more than once) that I'm sure someone somewhere must already have determined whether or not there can be a solution, though I don't know where to look or what to search for. Any ideas? Thanks, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Functional GUI combinators for arbitrary graphs ofcomponents?
Brian Hulley wrote: Anyway to get to my point, though all this sounds great, I'm wondering how to construct an arbitrary graph of Fudgets just from a fixed set of combinators, such that each Fudget (node in the graph) is only mentioned once in the expression. To simplify the question, assume we have the following data structure to describe the desired graph: data LinkDesc a = Series a a | Broadcast a [a] | Merge [a] a type GraphDesc a = [LinkDesc a] The above is more complicated than necessary. The problem can be captured by: type GraphDesc a = [(a,a)] Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [Haskell] Defining Cg, HLSL style vectors in Haskell
Slavomir Kaslev wrote: I have to define a couple of float2, float3, float4 Cg, HLSL style vectors in Haskell. At first I was tempted to make them instances of Num, Floating, RealFrac, etc. but some of the functions defined in those classes have no sense for vectors. I'd suggest that this implies that these classes are not suitable for Vectors. One such example is signum from class Num. There are several workarounds for this. One may come up with some meaning for vectors of such functions, for example: instance Num Float3 where . signum a | a == Float3 0 0 0 = 0 | otherwise = 1 This looks a bit unnatural. Also, testing equality of Floats is not generally recommended. [snip] I know that I can scrap all those Num, Floating, RealFrac, etc. classes and define class Vector from scratch, but I really don't want to come up and use different names for +, -, etc. that will bloat the code. While it may be tempting to want to use symbolic operators like + and -, these quickly become very confusing when more distinctions need to be made (eg between cross product, dot product, and scaling, or between transforming a position versus transforming a direction) so I'd argue that for readability descriptive names are better than symbols: class Num a = Vector v a where plus :: v a - v a - v a minus :: v a - v a - v a cross :: v a - v a - v a dot :: v a - v a - a scale :: a - v a - v a magSquared :: v a - a class Num a = Transform mat vec a where transformPosition :: mat a - vec a - vec a transformDirection :: mat a - vec a - vec a instance Num a = Transform Mat44 Vec4 a where -- ... If you're doing matrix transformations, you might also like to consider using separate PositionN and DirectionN types instead of VecN to make use of the type system to catch some math bugs but I haven't looked into this myself yet so I don't know whether this would be practical or not. Best regards, Brian. -- http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Why instances can't be hidden (was: non-total operator precedence order)
Benjamin Franksen wrote: Henning Thielemann wrote: On Fri, 10 Nov 2006, Benjamin Franksen wrote: Although one could view this as a bug in the offending module it makes me somewhat uneasy that one additional import can have such a drastic effect on the code in a module /even if you don't use anything from that module/. It's the same as with instance declarations, isn't it? I don't want to defend the problems arising with todays anonymous instance declarations, Right. However, with instances I can imagine solutions that avoid naming them, that is, I could imagine to write something like select instance C T1 T2 ... Tn from module M or import M hiding (instance C T1 T2 ... Tn, ) Such a feature could prove extremely useful in practice. Disclaimer: I am almost sure that there is something I have overlooked that makes such a simple solution impossible, otherwise it would have been proposed and implemented long ago... I think the reason you can't do this kind of thing is that within any set of modules that is compiled at the same time, anywhere in any of these modules, if you have a type T that's an instance of class C, then all occurrences of C T must refer to the exact same instance declaration or else things would get totally messed up when/if the compiler did whole program optimization. In other words, the instances are actually properties of the type(s) themselves so allowing different modules to see different implementations of the instances would break the conceptual merging of modules (modulo renaming) that occurs at compile time. Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Automatic fixity allocation for symbolic operators
Jim Apple wrote: On 10/14/06, Brian Hulley [EMAIL PROTECTED] wrote: User defined fixities are an enormous problem for an interactive editor This is the second or third time you've proposed a language change based on the editor you're writing. I don't think this is a fruitful avenue. Bertram Felgenhauer wrote: Brian Hulley wrote: infixr 9 .!! 99.9 Ouch. As far as editors go I have little sympathy. Nicolas Frisby wrote: I think it's unreasonable to tie programmers' hands for the sake of off-loading rather trivial tasks to editors. J. Garrett Morris wrote: On 10/14/06, Nicolas Frisby [EMAIL PROTECTED] wrote: Perhaps the editor could assume a default precedence ... I agree that changing the language in such an unintuitive way - breaking existing code in the process - to suit an editor is counterproductive and ridiculous. I feel that the example I used of an interactive editor has somewhat eclipsed the purpose of my post, which was basically to see if there is some way to arrive at an agreed association of operator precedences with symbolic ops such that this would include the current Prelude operators and have some kind of intuitive extension to all other possible symbolic ops which would respect one's expectations that * and + should be similar to * and + in terms of relative precedence and absolute associativity. After all, if a library writer decided to make * bind more loosely than + one might justifiably be frustrated at the apparent inconsistency therefore why not just make all this systematic and fixed down to remove these problems? I had thought perhaps someone might have already made such a global operator table suitable for functional programming, or some suitable algorithm hence the inclusion of my first stumbling attempt at one to try and set the ball rolling and at least save someone else several hours of hard work going down the same dead end if such it is. Jim Apple wrote: There are three ways to change Haskell's lexical structure: 1. DIY on an open-source compiler/interpreter of your choice. 2. Write your own compiler/interpreter. 3. Get the change into Haskell''. If the Haskell'' procedure is like the Haskell' procedure, you'll have to do 1 or 2 before you do 3. It's possible that you will convince someone that your syntax changes are worth doing, and that this person will do step 1 or step 2 for you, but I don't think so. I haven't done the research myself, but I think if you look at the source control logs for Your Favorite Haskell Compiler/interpreter and the HCAR, you will find very few commits/projects devoted to syntax. I think this is because Haskellers are much more interested in semantics. Afaiu the whole concept of type classes arose because of the desire to avoid having to think up different names for related functions and MPTCs were suggested by the syntax for single parameter TCs (though I can't remember the reference where I think I remember reading this latter point). Proposing changes that break existing code or segment the Haskell code base just doesn't seem like a win. Since all syntactic and many semantic changes necessarily break existing code or segment the code base this would seem to imply that the language should not be changed at all or that everything must be backwards compatible, so that we have to drag the Achilles heel of original mistakes around for all eternity. I'd have thought a solution would be to just use a tool to automatically convert existing code to whatever new syntax is found to be better, thus allowing the language to be gradually perfected as more and more issues are brought to light. Still I agree with you that a more sensible approach in terms of someone like me writing an editor is simply for me to take Haskell as an inspiration and incorporate my ideas in it so that any changes can later be seen in relation to a (hopefully facilitated and enjoyable) programming experience rather than trying to share my ideas piecemeal and insufficiently contextualized as they arise. Thanks to all who replied, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Automatic fixity allocation for symbolic operators
Hi - I'm wondering if it is possible to construct a methodical procedure to assign a fixity to symbolic operators so that we could get rid of the need for user defined fixites. User defined fixities are an enormous problem for an interactive editor, because it is not possible to construct a parse tree of some code if you don't know what the fixities are, and an editor must be able to do something useful with a code fragment without having to look inside other modules (because the other modules may not yet have even been written!). Also, the programmer or reader of code needs to be able to understand each code fragment independently as well. From the Haskell98 report, the Prelude defines: infixr 9 ., !! infixr 8 ^, ^^, ** infixl 7 *, /, `quot`, `rem`, `div`, `mod` infixl 6 +, - infixr 5 :, ++ infix 4 ==, /=, , =, =, infixr 3 infixr 2 || infixl 1 , = infixr 1 = infixr 0 $, $!, `seq` Suppose we ignore the varid operators and just consider the symbolic ops. What I'm trying to find is a systematic way to assign fixities to all other possible sequences of symbol characters that is consistent with what we've already got in the Prelude. As a first step, we could say that mirrored operators must share the same precedence ie: == For associativity, we could assign each character an associativity weight: -1 left associative 0neutral 1right associative and say that the associativity is simply the sign of the sum of the associativity weights of the characters thus: -1 =0 1 =0 + 1 + 1ie infixr Note that I don't care about non-associative ops since the non-associativity of something should be a question for the type checker not the parser imho - ideally we should be able to create a parse tree for any possible operator expression. To form the precedence, we could assign each character a precedence value eg: 9 .! 8^ 7*/ 6+- 5: 4= 3 2| 1 0$ A first attempt might be to say that the precedence is simply the decimal expansion of the precedence values eg = has precedence 1.14 and $! has precedence 0.9. However, as noted above, mirrored ops must share the same precedence so an alternative is to create some ordering of characters such that when the set of characters in an operator is sorted according to this ordering, the decimal expansion of the precedence digits will give the same relative ordering for operator precedences as the Prelude. For example, using $ | + - * / ^ . ! : = as the ordering, we'd get: infixr 9 .!! 99.9 infixr 8 ^, ^^, **8 8.87.7 infixl 7 *, /,77 infixl 6 +, -6 6 infixr 5 : , ++ 56.6 infix 4 ==, /=, , =, =, 4.4 7.4 11.41.41 infixr 3 3.3 infixr 2 ||2.2 infixl 1 , =1.11.14 infixr 1 =1.14 infixr 0 $, $!00.9 Although most existing ops get a similar precedence (eg ^ ^^ and ** are all still in the same group relative to the other ops despite the fact that within the group there is now an ordering) the main problem seems to be that = = get precedences that bind too loosely and /= is totally wrong. This problem aside, the above algorithm would give sensible precedences for such things as: :: 5.1 +*6.116.11 where the use of neutralizes the associativity contribution of or respectively (since (-1) + 1 == 0), giving us the intuitive associativity we'd expect from the interesting character in the middle. (The problem of /= getting 7.4 could be solved by putting / after = in the order, to get 4.7, but unfortunately this would mean that since must be before =, would be before / so / would get the wrong precedence compared to *) Another issue is that there is no assignment of associativity weights such that * is infixl but ** is infixr (ditto + and ++) so perhaps we'd need to associate each character with an associativity function. Similar to precedences, we then define an associativity ordering and let the resulting associativity be the sign of the composition of the sorted functions applied to 1 eg: ^ const (-1) * \x - x * (-1) = id const (-1) (+1) (+ (-1)) Then *(\x - x * (-1)) 1===-1 ie left ** (\x - x * (-1)) . (\x - x * (-1)) $ 1 === +1 ie right = = (+ (-1)) . (+ (-1)) . id$ 1 === -1 *-- remember ordering
Re: [Haskell-cafe] A type in search of a name...
Albert Lai wrote: Brian Hulley [EMAIL PROTECTED] writes: You'll never believe it but I've been struggling last night and all of today to try and think up a name for the following type and I'm still nowhere near a solution: data ??? = VarId | VarSym | ConId | ConSym Perhaps Atom. Thanks for the suggestion, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Vertical tabs in source code and other obscure chars
Brian Hulley wrote: Hi, In the Haskell98 report at http://haskell.org/onlinereport/lexemes.html section 2.2 has the rule: whitechar - newline | vertab | space | tab | uniWhite Does anyone know what a vertical tab is supposed to do? Is there any reason to allow them as whitespace? (Does anyone in the universe actually use them?) To rephrase my question, what is a Haskell lexer/parser supposed to do when it encounters a vertical tab? The description of the layout rule in the report does not specify what a vertical tab means. If no-one knows the answer, perhaps the rule should be changed to: whitechar - newline | space | tab | uniWhite and a vertical tab's could just be treated as illegal characters. Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] A type in search of a name...
Hi, You'll never believe it but I've been struggling last night and all of today to try and think up a name for the following type and I'm still nowhere near a solution: data ??? = VarId | VarSym | ConId | ConSym this is part of a type to describe Haskell lexemes: data Token = TName !??? !ByteString.T | ... Here are some of my attempts to fill in ??? and my reasons for rejecting them: 1) VarConIdSym - the problem is that it's too long and the first letter is 'v' which could be confused with the letter 'V' in VarId or VarSym 2) Name - the problem is that this suggests the string itself rather than the VarId/VarSym/ConId/ConSym'ness of the token 3) NameType - I'm trying to avoid using the words Type Kind etc because I'll probably want to use these later for other things and in any case NameType suggests the type of a lexical name ie Token itself 4) Space - this can be confused with something to represent whitespace or the namespaces introduced by modules 5) Just using data Token = TVarId !BS.T | TVarSym !BS.T | ... -- explodes into too many different cases when you add tokens for qualified names and all their variations (since I'm also representing incomplete tokens like Foo. and Foo.where (as a prefix of Foo.whereas etc since it can't stand by itself because where is a reserved word)) 6) Using Bool as in data Token = TName !Bool !Bool !BS.T -- problem is that then I won't get any help from the typechecker if I accidentally confuse the order of Bools when matching etc. I could use the record syntax but then code can become very clunky to look at and it would still allow the Bools to get confused when they are passed about Any ideas? I must say that trying to think up names for things is absolutely the most difficult task in programming imho. The problem is that once fixed down, a name gets used all over the place and becomes totally entrenched in the code and affects how one thinks about the code thereby influencing its whole future development in a very deep and pervasive way (think suffixes/ prefixes/ relationships with other concepts etc). I would also be satisfied with just good names for the following types: data ???1 = Var | Con data ???2 = Id | Sym data ???3 = Op | Plain (I just combined ???1 and ???2 in ??? to try and save some space in the representation but ideally they would be separate types if only there were a way to tell the compiler to represent each by 1 bit in a word at the machine level like C's struct {VarCon vc : 1; IdSym is : 1;}) Any suggestions welcome, Thanks, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Vertical tabs in source code and other obscure chars
Hi, In the Haskell98 report at http://haskell.org/onlinereport/lexemes.html section 2.2 has the rule: whitechar - newline | vertab | space | tab | uniWhite Does anyone know what a vertical tab is supposed to do? Is there any reason to allow them as whitespace? (Does anyone in the universe actually use them?) Thanks, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haskell performance (again)!
Lennart Augustsson wrote: I think your first try looks good. [snip] ... addPoly1 p1@(p1h@(Nom p1c p1d):p1t) p2@(p2h@(Nom p2c p2d):p2t) | p1d == p2d = Nom (p1c + p2c) p1d : addPoly1 p1t p2t | p1d p2d = p1h : addPoly1 p1t p2 | p1d p2d = p2h : addPoly1 p1 p2t ... The last comparison is redundant (this was in the original version too) because p1d p2d is implied (certainly for this case where p1d, p2d::Int) by the fall through from not satisfying == and so how about: addPoly1 p1@(p1h@(Nom p1c p1d):p1t) p2@(p2h@(Nom p2c p2d):p2t) | p1d == p2d = Nom (p1c + p2c) p1d : addPoly1 p1t p2t | p1d p2d = p1h : addPoly1 p1t p2 | otherwise = p2h : addPoly1 p1 p2t Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Either as a Monad instance
Ross Paterson wrote: On Tue, Oct 03, 2006 at 07:52:54AM -0400, Lennart Augustsson wrote: Yes, having fail in the Monad is a horrible wart. (As far as I know, it's there for the translation of pattern match failure in do-expressions.) I think it would be much less of a wart if the signature for fail was just: fail :: m a because what's the point of the String argument anyway (other than trying to hack a kind of half-baked debug facility into the language)? Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] smallest double eps
Lennart Augustsson wrote: Hang on, hang on, now I'm getting confused. First you asked for the smallest (positive) x such that 1+x /= x which is around x=4.5e15. 1 + 0 /= 0 0 is smaller than 4.5e15 So I don't understand this at all... Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] smallest double eps
Thomas Davie wrote: On 30 Sep 2006, at 17:19, Brian Hulley wrote: Lennart Augustsson wrote: Hang on, hang on, now I'm getting confused. First you asked for the smallest (positive) x such that 1+x /= x which is around x=4.5e15. 1 + 0 /= 0 0 is smaller than 4.5e15 So I don't understand this at all... But then 0 isn't positive. Why not? In any case every positive number nust satisfy the above inequation so what about 0.1, which is certainly smaller than 4500? Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: A better syntax for qualified operators?
Benjamin Franksen wrote: Brian Hulley wrote: ith = Data.Array.IArray.(!) Sorry, but I can't see the problem here. Why can't the editor offer the operator as '!' in the list of options, and if the user selects it insert both '(' and ')' at the right places (i.e. before the module name and after the operator)? Is there some unwritten law that forbids editors or IDEs to insert stuff at positions other than the current cursor position? I hadn't thought of that - I've now decided to just use the existing syntax here. Generally speaking, I would always hesitate to change the language so it better suits programming tools(*). It is the tools which should adapt to the language, even if that means the programmer has to find new ways of suporting the user (and the language). The most important reason being that code is more often read than written. My motivation for the change was that it would better suit the human user of the programming tool, though in this particular instance you and Henning have convinced me that the original syntax was better after all. At the danger of becoming completely off-topic now (sorry!), I have to say that I find /both/ versions ugly and unnecessarily hard to read. My personal solution is to generally avoid qualified imports. How does this solution scale? Surely it's only lucky if people happen to choose names that don't clash with those of other modules? I use it only if absolutely necessary to disambiguate some symbol, and then just for that symbol. I am aware that there is an opposing faction here, who tries to convinve everyone that qualified import should be the standard (and the actual exported symbols --at least some of them-- meaningless, such as 'C' or 'T'). Although C and T are in themselves meaningless, the name of the module itself is not. As I understand it, this convention makes the module name carry the meaning so you use Set.T instead of Set.Set where the meaning is duplicated (a rather uneasy situation) in both the module name and type name. I think such a convention is inappropriate for a functional language (especially one with user defined operators). There simply is no natural 1:1 correspondence between data type declaration and functions acting on that data built into the language, as opposed to e.g. OO languages. Extensibility in the functional dimension, i.e. the ability to arbitrarily add functions that operate on some data without having to change the code (module) that defines the data, is one of the hallmarks of functional programming, as opposed to OO programming. If you have an abstract data type then it *is* like an object (though in a potentially more powerful way than in OOP) because there is no other way to manipulate values of that type. If the type is not abstract, the advantage of calling it T is just that it avoids naming it twice (by type name and module name) in the situation where you want to not worry about name clashes with constructors of other types. However, nothing prevents us from offering two interfaces (visible modules), one where the data type is abstract (client interface) and a different one where it is concrete (extension interface) You can still call both types T... :-) Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] A better syntax for qualified operators?
Brandon Moore wrote: Brian Hulley wrote: I would *like* to be able to use the syntax: ith = Data.Array.IArray.(!) Why does the nice argument not apply equally well to infixifying things? Shouldn't I be able to write myArr Data.Arr.`get` ix Good point. This would also remove the need for allowing double conversion as in OpIdOp which was an element of asymmetry in my original proposal. Thus I revise my proposal to the following: varId ::= id varOp ::= symbol varIdOp ::= ` varId ` varOpId ::= ( varOp ) qx ::= {conId .}+ x so the concerns of qualification and Id, Op, Id-Op would now be separated (the point being that you can only make a decision regarding Id-Op when you know whether or not you're starting with an Id or an Op and you only know this latter fact when you've already arrived at the module by typing the qualifier). (Also the trailing backquote in the existing syntax is redundant) The trailing backquote is just as redundant as the trailing close paren in the syntax for using a symbol as a prefix function and just as important for my comment on backticks as the closing paren is to your proposal for sections - it means it's lexically apparent at least at one side of the identifier that it's a section/infixification I'm not sure I understand this argument for why a trailing backquote is needed, though I can see it would be needed if the dist-fix idea proposed by Benjamin Franksen in http://www.haskell.org/pipermail/haskell-cafe/2006-August/017373.html was adopted eg: Control.K.`if cond Control.K.`then` t Control.K.`else` f Control.K.fi` Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] flip dot
On Thursday, September 28, 2006 1:33 AM, Greg Fitzgerald wrote: Since there's talk of removal of the composition operator in Haskell-prime, how about this: Instead of: foo = f . g you write: foo = .g.f A leading dot would mean, apply all unnamed parameters to the function on the right. A trailing dot would mean, apply the result of the left to the function on the right. Hi - I think the H' proposal http://hackage.haskell.org/trac/haskell-prime/wiki/CompositionAsDot is an extremely bad idea. I really don't see why people have so many problems with the idea of just placing spaces before and after the dot when used as an operator, and in any case it's hard to think of a more important operator in a functional language than composition and a more fitting symbol for it than the simple dot. Also, the syntax .x with no spaces between the '.' and the 'x' is needed for at least one record poposal (eg http://www.haskell.org/pipermail/haskell-cafe/2006-August/017466.html) Regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] A better syntax for qualified operators?
Hi - Consider the scenario when you want to find a function that returns the i'th element of an array but all you know is that there is a module called Data.Array.IArray that will probably have such a function in it. So you start typing in your program: let ith = Data.Array.IArray. at this point, you'd hope the editor you're using would somehow display a list of avaliable values exported from Data.Array.IArray including the indexing function, so you could select it, thus I would *like* to be able to use the syntax: let ith = Data.Array.IArray.(!) because it's not the user's fault that the person who wrote Data.Array.IArray decided to use a symbol instead of an identifier for this function - the user of Data.Array.IArray in this case just wants to see normal identifiers to use with prefix application so the use of (!) at this point effectively gets rid of the unwanted operatorness associated with the function. However the current syntax of Haskell would not allow this. Instead you have to write: let ith = (Data.Array.IArray.!) The problem is that the user of Data.Array.IArray has to know already in advance, before typing the 'D' of Data, that the indexing function has been named with a symbol instead of an identifier, but this knowledge is only available later, when the user has typed the '.' after IArray, so the current syntax would be frustrating for the user because the user then has to go all the way back and insert an opening paren before the 'D'. Also, consider the appearance of: let ith = (Data.Array.IArray.!) arr i b = Data.Array.IArray.bounds arr vs let ith = Data.Array.IArray.(!) arr i b = Data.Array.IArray.bounds arr I'm not sure if I've managed to explain this problem clearly enough, but my proposal is that we might consider changing the lexical syntax of Haskell as follows: varId ::= id varOp ::= symbol varIdOp ::= ` varId varOpId ::= ( varOp ) varOpIdOp ::= ` varOpId qvarId ::= {conId .}+ varId-- { }+ denotes 1 or more times qvarIdOp ::= ` qvarId qvarOp ::= {conId .}+ varOp qvarOpId ::= {conId .}+ varOpId qvarOpIdOp ::= `qvarOpId In other words, to turn an operator symbol into an id, the parentheses would be put immediately around the symbol (with no spaces since this is lexical syntax), and to turn an id into an operator the backquote is put in front of the entire (qualified) id. (Also the trailing backquote in the existing syntax is redundant) The above syntax would have 3 advantages: 1) It allows the client of a module to write code without having to worry if the author of the module used symbols or identifiers to name functions - everything exported from the module can be made to appear as if it was named by an identifier (ie OpId) 2) Moving the parentheses to the lexical syntax makes syntax highlighting easier (because there are no comments to worry about inside the OpId) and also makes parsing simpler because all the mess associated with Ops versus Ids is handled by the lexer 3) It allows an editor to make a distinction between (+)-- an operator turned into an identifier - varOpId ( + ) -- an expression with 2 gaps in it which should be marked as incomplete (+ ) -- a section with 1 gap Some examples of the proposed syntax are: let ith = Data.Array.IArray.(!) arr i foo = k `Math.(+) 6-- default precendence bar = k Math.+ 6-- using precedence of + in module Math When you try to write an editor for Haskell (or some subset of it), you quickly discover these areas of Haskell syntax like the above which need to be changed to get an optimum interactive editing experience. I think it *is* possible to adjust the Haskell grammar so that it is LL(1) and the only reason it is not already LL(1) seems to be that the grammar has been designed with compilers (which only need to deal with complete modules) in mind rather than programmers interactively editing in mind. (The other change needed for LL(1) is to give contexts a marker before they appear eg: foo :: {MonadIO m} a - m a ) By LL(1) I'm really meaning that the grammar for interactive editing needs to be adjusted so that it is possible to maintain the invariant that as code is entered from left to right constructs and identifiers can be highlighted according to their grammatical role and highlighting (modulo incompleteness) must remain unchanged regardless of whatever is typed afterwards to the right otherwise it can become more of a liability than a help, hence my hope that some future revision of Haskell grammar might consider taking the above points into account. Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us.
Re: [Haskell-cafe] Writing forum software in Haskell
David House wrote: Hi all. The recent thread on email vs. forums inspired a bit of interest to get some forum software on haskell.org. Were we to go ahead with this, I think it'd be great to have this software written in Haskell itself. [snip] * What kind of forum are we aiming at? In my eyes, it'd be less like the bloated phpBBs out there full of oversized signatures and avatars, and more like the minimalistic bbPress on show at, for example, the WordPress support forums [1]. * What would be a compulsory feature list? 1) I think anyone who posts should first have to register to avoid the problem of spam. 2) I think it would be good if it was possible to get away from the usual tree structure of posts. By this I mean that usually you have to choose a post to reply to, which is awkward if you want to comment on more than one previous post because then it's not clear what post to choose as the parent. As a rough idea, perhaps something which considered paragraphs(*) as the basic unit of discourse ie data Post = Post {_author :: !Author, _time :: !Time, _topic :: !Topic, _paras :: ![PostPara]} data PostPara = Own !Paragraph | Quoted !PostPara !Author !Time !Topic data Paragraph = Text !ByteString | Code !ByteString and I'd imagine posts being edited using an editor which displayed a vertical sequence of PostPara's (ie edit boxes for the paragraphs you've written yourself and some other widget involving a static text box to display paras that you're quoting) Multiple consecutive paras that you write yourself would just be written in the same edit box. Actually the whole post could be written in one edit box if there was a special escape syntax for quoting (you'd select some text in some other post then click quote and it would be pasted into the post you're composing surrounded by the appropriate escape sequences and source info, and like the wiki editor, you could click preview to see how the whole thing would look when posted). This would give full support for DAG based discussions. (At the moment in the mailing list if I want to reply to more than one person I have to click reply on each email I'm replying to and cut and paste the indented text from the second person's email into my reply to the first and hope that I don't accidentally send the second blank reply by mistake, and if someone has chosen to include a signature with their message or sent it using HTML instead of plain text I have to manually indent each individual line myself because Outlook Express doesn't display the text of signed messages but instead puts it into a file like ATT12.txt...) (*) Of course the above representation doesn't give any way to only quote part of a paragraph or to split paragraphs up so it might be too inflexible. It might also not be clear what should be regarded as a paragraph. Perhaps span of text would be a better unit of discourse. 3) It would be nice if there was a way to put something in the centre to be discussed from different angles, instead of always being stuck with a linear flow, where important points made in previous posts can just get ignored altogether because they are too far back in linear time. The scenario I'm thinking of is: 3a) Person A makes 2 good points, A1 and A2 3b) Person B replies to A1 3c) Person C replies to B's reply of A1 3d ) Long discussion about A1 3e) A2 has completely been forgotten and is never addressed I'm imagining a visual representation of the text in the centre with the discussion around it though perhaps this is getting too complicated for what's possible just with HTML. 4) Another nice feature would be the ability to just say cool or yes or no without having to actually make a real post like a kind of vote for or against an idea. Anyway best of luck with whatever forum people come up with. I originally used to post to the mailing list using the Google group fa.haskell (strange name!!!) but though I liked the Google interface the posting didn't work properly - my posts were delayed several days and sometimes never got there at all. Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Why am I not allowed to use CStringLen inforeignexport?
Andreas Marth wrote: low_l :: Word8 = fromIntegral (len .. 0x) low_h :: Word8 = fromIntegral (shiftR len 8 .. 0x) high_l :: Word8 = fromIntegral (shiftR len 16 .. 0x) high_h :: Word8 = fromIntegral (shiftR len 24 .. 0x) Hi - I just noticed the mask should be changed to 0xFF for the BSTR8 version above. Also, I'm not actually sure if a mask is needed at all. I just used one to make sure there would be no chance of an overflow exception being thrown, but the Haskell report doesn't seem to specify anything at all about the behaviour of (fromIntegral) when converting between types of different sizes. Perhaps someone on the list can clarify whether or not a mask is needed ie is fromIntegral allowed to throw exceptions or does it always just silently discard unwanted bits of the argument being converted? Thanks, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Why am I not allowed to use CStringLen inforeignexport?
Andreas Marth wrote: Thanks a lot for this information it helped a lot. Glad to be of help. I am thinking about creating a wikipage about Haskell-VBA interfacing through a DLL. Is it okay for you if I put your code there? Yes. I am a bit concerned about the memory. newArray states that the memory has to be freed after usage. Is this needed here? How can it be done? One way could be to write a function which creates the BSTR, passes it to a function, then deallocates the BSTR before returning eg (untested): import Control.Exception (bracket) withBSTR8 :: [Char] - (BSTR8 - IO a) - IO a withBSTR8 s f = bracket (createBSTR8 s) (\bstr - free (bstr `plusPtr` (-4))) (\bstr - f bstr) Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: ambiguous partially defined type problem
Maarten wrote: Only update (see code below) is a bit ugly (I have no idea why I need fixCastUpdate) class (Show a, Typeable a) = ICustom a where [snip] update :: a - (forall b. (ICustom b) = b - b) - a update a f = f a instance ICustom Node where getVal (Node n) f = getVal n f update (Node n) f = Node (update n f) updateM :: forall a b. (ICustom a, ICustom b) = (a - b) - NodeState () updateM f = do s - get let s' = update s (fixCastUpdate f) put s' Hi Maarten - Looking at this again, I wonder if the following changes would work: -- this change is not strictly necessary update :: a - (a - a) - a updateM :: (forall a. ICustom a = a - a) - NodeState () updateM f = do s - get let s' = update s f put s' I think the reason why fixCastUpdate was needed in your original definition of updateM is because the type of f seems to be too general (a-b) compared to the type of f in the update method of ICustom (b-b) Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: ambiguous partially defined type problem
Brian Hulley wrote: -- this change is not strictly necessary update :: a - (a - a) - a Sorry - I just looked again at the instance decl for Node, so the above change should not be made. Apologies for the multiple posts, I must try to think more before clicking send ;-) Regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Why am I not allowed to use CStringLen in foreignexport?
Andreas Marth wrote: Hi! I try to export a Haskell function to VBA. (At the moment without COM.) Because VBA seems to expect a String with length information I tried to return a CStringLen as defined in Foreign.C.String. But if I try to compile it I get an unacceptable argument type in foreign declaration: CStringLen. My reduced test program now is a strange Hallo world! program: module Test where import Foreign.C.String foreign export stdcall hello :: IO CStringLen hello :: IO CStringLen hello = donewCStringLen (Hallo world!) Do I do some thing wrong here? (If I use CString instead of CStringLen and accordingly newCString instead of newCStringLen everything compiles fine but VBA crashes.) The FFI only supports a very limited range of types. CString is supported because it is just defined by: type CString = Ptr CChar whereas CStringLen is defined as (Ptr CChar, Int) and tuples can't be passed through the FFI. In any case, the BSTR type required by VBA is not so simple as a CStringLen. From the Microsoft Platfrom SDK docs, BSTRs are wide, double-byte (Unicode) strings on 32-bit Windows platforms and narrow, single-byte strings on the Apple® PowerMacT. The length is stored as an integer at the memory location preceding the data in the string. I assume that this means that on 32 bit Windows, the format of a BSTR is: Word16 -- low word of length Word16 -- high word of length Word16 -- first char of string ... so you could try creating an array of Word16's in that format and passing them, perhaps something like: import Data.Word import Data.Bits import Foreign.Marshal.Array import Foreign.Ptr type BSTR = Ptr Word16 createBSTR :: [Char] - IO BSTR createBSTR s = do let len :: Word32 = fromIntegral (length s) low :: Word16 = fromIntegral (len .. 0x) high :: Word16 = fromIntegral (shiftR len 16 .. 0x) newArray ([low, high] ++ map (fromIntegral . fromEnum) s) foreign export stdcall hello :: IO BSTR hello :: IO BSTR hello = createBSTR Hello world! (The above code compiles but is untested) Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Why am I not allowed to use CStringLen inforeignexport?
Brian Hulley wrote: I assume that this means that on 32 bit Windows, the format of a BSTR is: Word16 -- low word of length Word16 -- high word of length Word16 -- first char of string ... The above is not quite correct. It appears from http://www.oreilly.com/catalog/win32api/chapter/ch06.html that the length must preceed the actual BSTR, thus you must give VBA a pointer to the first *char* in the string not the actual start of the array of Word16's in memory. Furthermore, it appears that a terminating NULL is still needed even though the string itself can contain NULL characters. No only that, but the length must be given as the number of *bytes* (excluding the terminating NULL) not the number of characters. Therefore here is a revised attempt at creating a Win32 BSTR: import Data.Word import Data.Bits import Foreign.Marshal.Array import Foreign.Ptr type BSTR = Ptr Word16 createBSTR :: [Char] - IO BSTR createBSTR s = do let len :: Word32 = fromIntegral (length s * 2) low :: Word16 = fromIntegral (len .. 0x) high :: Word16 = fromIntegral (shiftR len 16 .. 0x) arr - newArray ([low, high] ++ map (fromIntegral . fromEnum) s ++ [0]) return $! plusPtr arr 4 foreign export stdcall hello :: IO BSTR hello :: IO BSTR hello = createBSTR Hello world! Regards, Brian. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ambiguous partially defined type problem
Maarten wrote: For a project involving I use some partially defined node (in this case a simple record, in my project state transformers) in which the defined part is common to all nodes, and the custom part is different for each node. They have to become anonymous so I can put them in a list of connections from each node to another. For some reason GHC complains of 'ambigous type variable' in the code below. The thing is, part of the code may be undefined, but since I'm (explicitly) not using that part, why would GHC care? Are there other solutions to this problem? Any pointers or comments appreciated. -- data structure with custom and common part data Node cust = Node cust Common deriving (Show,Typeable) -- anonymous data structure to put use in list data AN = forall ar. (Show ar, Typeable ar) = AN ar instance Show AN where show (AN an) = AN ( ++ show an ++ ) -- common part data Common = Common Integer deriving (Show,Typeable) data Custom = Custom Integer deriving (Show,Typeable) data Custom2 = Custom2 Integer deriving (Show,Typeable) -- extract common part, ignoring type of custom part getCommon :: forall gc. (Node gc) - Common getCommon (Node cust com) = com main = do let a = AN (Node (Custom 5) (Common 10)) let b = case a of (AN a') - getCommon (case (cast a') of Just a'' - a'') putStrLn $ ok: ++ show b Hi Maarten - The problem is that AN is far too general. The compiler can't tell that you've wrapped a Node, so the call to getCommon will fail to typecheck. Even if the compiler did know, by some other means, that a Node had been wrapped, Haskell doesn't support true existentials, so the type signature for getCommon doesn't do what I think you mean ie: getCommon :: forall gc. (Node gc) - Common is the same as writing: getCommon :: Node gc - Common whereas you'd really need an existential: getCommon :: (forall gc. Node gc) - Common The fact that gc is not used in the definition of getCommon doesn't matter, since the type system has to just use the same rules for type inference regardless of the content of the function. In other words, without true existentials, or some other extension to the type system, there is no way to propagate the fact that the actual binding for a type variable is never required. Also, AFAIK there is no guarantee that Node Int Common and Node String Common would always be laid out in memory in the same way - the compiler is allowed to use special optimized layouts for particular instantiations of cust (even though it probably won't be clever enough to do this at the moment in Haskell implementations). I suggest you wrap the custom part separately instead of wrapping the whole Node eg: data Custom = forall cust. ICusom cust = Custom cust data Node = Node Custom Common where the ICustom class is whatever class you need to be able to do anything useful with cust. Alternatively, you could wrap the custom part within the node as in: data Node = forall cust. ICustom cust = Node cust Custom getCommon :: Node - Common getCommon (Node cust com) = com Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Numeric type classes
Henning Thielemann wrote: On Wed, 13 Sep 2006, Lennart Augustsson wrote: I don't think Haskell really has the mechanisms for setting up an algebraic class hierarchy the right way. Consider some classes we might want to build: SemiGroup Monoid AbelianMonoid Group AbelianGroup SemiRing Ring ... The problem is that going from, say, AbelianMonoid to SemiRing you want to add a new Monoid (the multiplicative) to the class. So SemiRing is a subclass of Monoid in two different way, both for + and for *. I don't know of any nice way to express this is Haskell. Thanks for confirming what I wrote. :-) If the above is equivalent to saying Monoid is a *superclass* of SemiRing in two different ways, then can someone explain why this approach would not work (posted earlier): data Multiply = Multiply data Add = Add class Group c e where group :: c - e - e - e identity :: c - e inverse :: c - e - e instance Group Multiply Rational where group Multiply x y = ... identity Multiply = 1 inverse Multiply x = ... instance Group Add Rational where group Add x y = ... identity Add = 0 inverse Add x = ... (+) :: Group Add a = a - a - a (+) = group Add (*) = group Multiply class (Group Multiply a, Group Add a) = Field a where ... If the objection is just that you can't make something a subclass in two different ways, the above is surely a counterexample. Of course I made the above example more fixed than it should be ie: class (Group mult a, Group add a) = Field mult add a where ... and only considered the relationship between groups and fields - obviously other classes would be needed before and in-between, but perhaps the problem is that even with extra parameters (to represent *all* the parameters in the corresponding tuples used in maths), there is no way to get a hierarchy? Thanks, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Weak pointers and referential transparency???
[EMAIL PROTECTED] wrote: Brian Hulley wrote: [...] Ref.write proxiesRef $! (weakProxy : proxies) (This is nothing to do with your main question, but the strict application looks unnecessary there. Its right hand side is already a constructor cell.) Yes, thanks for pointing this out. [...] In other words, if the entry for the proxy in the table stored in the Model dies, can I be absolutely 100% sure that this means the proxy no longer exists in any shape or form in the running program? My reading of the semantics (http://haskell.org/ghc/docs/latest/html/libraries/base/System-Mem-Weak.html#4) is that you can be sure the proxy *object* is gone. My problem is that I don't know what to make of the word object in the context of Haskell ie when can I be sure that a value is actually being represented as a pointer to a block of memory and not stored in registers or optimized out? Or is the compiler clever enough to preserve the concept of object despite such optimizations? I had been designing my Model/Proxy data types with the Java notion of everything is a pointer to an object but is this always correct relative to Haskell as a language or is it just a consequence of the current GHC implementation? As for referential transparency... Fan-in: If you create equivalent proxies in different calls to createProxy, it's possible that they'll end up referring to the same object (e.g. if the compiler or RTS does something fancy, or you use a memoised smart constructor). So then a single live proxy object *could* protect many elements of your Weak Proxy list from scavenging. Fan-out: It would seem perverse to cry referential transparency! and spontaneously clone one of your proxy objects. That *could* lead to deRefWeak returning Nothing while an *equivalent* Proxy object is still alive. Might you run your program on an avant-garde distributed RTS? ;-) Someone else might even if I don't! ;-) In the meantime I found a better solution to my original problem without needing to use weak pointers: I now make the proxy pull the changes from the model instead of making the model push them to all registered proxies, so there is no longer any need to have a table of registered proxies hence no need for weak pointers. Thanks, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Numeric type classes
Bryan Burgers wrote: That being said, I'll have to play the other side of the coin: it would probably be a little bit of a pain to have to define instances of each data declaration (Integer, Int, Float, Matrix, Complex, etc.) on each of these seperate classes--especially when being in a certain class usually implies being in another (ie, the definition of a set being a field requires that that set is a group, right?) Aaron Denney wrote: On 2006-09-12, Bryan Burgers [EMAIL PROTECTED] wrote: And another problem I can see is that, for example, the Integers are a group over addition, and also a group over multiplication; Not over multiplication, no, because there is no inverse. I know of no good way to express that a given data type obeys the same interface two (or more) ways. Some OO languages try to handle the case of of an abstract base class being inherited twice through two different intermediate classes, but none of them do it well. How about: data Multiply = Multiply data Add = Add class Group c e where group :: c - e - e - e identity :: c - e inverse :: c - e - e instance Group Multiply Rational where group Multiply x y = ... identity Multiply = 1 inverse Multiply x = ... instance Group Add Rational where group Add x y = ... identity Add = 0 inverse Add x = ... (+) :: Group Add a = a - a - a (+) = group Add (*) = group Multiply class (Group Multiply a, Group Add a) = Field a where ... Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe