[Haskell-cafe] Re: Beginner SOS
On Wed, 27 May 2009 15:04:36 -0700, Thomas DuBuisson thomas.dubuis...@gmail.com wrote: ?There are links to some great tutorials [1] and IRC information where you can get real-time help [2]. ?Also there are some good books [3]. I think most recent learners learned from YAHT [4], Gentle Introduction [5], and LYAH [6]. ?I personall read [3] [4] and eventually discovered [7], which is well written but last I checked isn't nearly a complete tutorial. Thomas Did you forget the actual URLs? Arrghhh, Indeed - that's what I get for copy/pasting between boxes. [1] http://haskell.org/haskellwiki/Tutorials [2] http://haskell.org/haskellwiki/IRC_channel [3] look for 'Real World Haskell' and 'The Craft of Functional Programming' [4] http://darcs.haskell.org/yaht/yaht.pdf [5] http://www.haskell.org/tutorial/ [6] http://learnyouahaskell.com/ [7] http://en.wikibooks.org/wiki/Haskell Another book that I would recommend is the following: Programming in Haskell by Graham Hutton http://www.cs.nott.ac.uk/~gmh/book.html Duncan Coutts has written a book review on this title, in which he highly recommends the book, at the following site: Book Review: “Programming in Haskell” by Graham Hutton by Duncan Coutts http://www.cs.nott.ac.uk/~gmh/book-review.pdf There is also an eBook version of the above-mentioned title available at the following site: eBooks.com - Programming in Haskell eBook http://www.ebooks.com/ebooks/book_display.asp?IID=307017 Please keep in mind that, unlike most other books and tutorials on Haskell, neither _Real World Haskell_ nor _Programming in Haskell_ assumes that the reader is highly mathematically-inclined. -- Benjamin L. Russell -- Benjamin L. Russell / DekuDekuplex at Yahoo dot com http://dekudekuplex.wordpress.com/ Translator/Interpreter / Mobile: +011 81 80-3603-6725 Furuike ya, kawazu tobikomu mizu no oto. -- Matsuo Basho^ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Design in Haskell?
Hi Dan, On Mon, May 25, 2009 at 1:22 AM, Dan danielkc...@gmail.com wrote: Hi, When I was learning to program in imperative languages like Java, there were plenty of resources to learn from about how to design large programs. Ideas like the GoF Design Patterns gave useful models that one could then scale up. I think GoF applies even in Haskell. Are there such resources for Haskell? As I'm learning the language, I'm finding it quite nice to write short programs (e.g. projecteuler, Haskell Road, etc.) But when I try to write something a bit larger, I find I'm tripping over myself and having a hard time organizing the code coherently. Many functional programming languages are actually multi-paradigm in that they support object oriented designs very well. There are a few well known differences though. For example, you won't find people using the visitor pattern in Lisp/Haskell, but you will find them using maps, folds, and scrap your boilerplate methods. Even in Haskell I still find myself thinking a lot about the data types I will use to represent the problem I'm solving; much like an object oriented designer would. One difference though, at this stage, is that I think about the program as a series of transformations of data. I start with a representation of the input, think about how I want to transform that, then define an intermediate representation. This pairing of transformations and representations continues until you have a suitable representation of the output, and then often you just show it. Think of type classes as interfaces in Java. They even support a restricted variation on subtyping if you chain them together. One design pattern from the GoF book that works especially well with Haskell is the interpreter pattern where you make a domain specific language and solve your problems using that language. At this point, we're just using a nice functional language the way we program in other languages. We can do more though. The real deep and interesting designs build on this space. By exploiting laziness we can make primitives which are more composable, so it pays to study the way laziness works. Learn other people's clever, lazy, solutions to those projecteuler problems. It can help you write more orthogonal parts in your program so that more of your program looks like a 'library' that you just happen to call. The exploits of laziness don't stop there. You can actually create data structures which represent control flow abstractions due to laziness. Monads, especially the continuation monad, are strong examples of this. The beauty of representing control flow abstractions with data structures in your language is that you can pass them around, that is they become first class, and also you can manipulate them. Monad Transformers being a strong example of this. In fact, many programs can be built by taking standard monads and mixing them together, one for each piece. The easiest way to mix monads together in this regard is to use monad transformers plus a feature such as new type deriving. This gives you a way to piece together the features you want into a brand new type that hides or renames the parts that don't make sense. And the deriving makes it that much easier, but is not strictly necessary. Now, still ready to take your designs up a notch? Well, enter type system exploits. There are essentially two directions you can go from here, a) type classes b) gadts. Oh, and now we have type families, so three directions these days. Using the above you can do all manner of things, some of which can be turing complete or cause the type checker to fail to terminate. People tend to refer to type hackery in units known as Olegs, with most of us doing just a millioleg design here and there. We applied gadt style type hackery in the darcs source code to remove an entire class of bug, mainly the ones that result from incorrectly manipulating a sequence of patches. My thesis explains the approach we took: http://blog.codersbase.com/2009/03/25/type-correct-changes-a-safe-approach-to-version-control-implementation/ Are there any suggestions of wikis, books or particularly well-architected and readable projects I could look at to about learn larger-scale design in Haskell? The best advice I can give you, is read/participate on haskell-cafe and #haskell on irc.freenode.net, and to read the proceedings from ICFP. Some really beautiful papers have come out of ICFP over the years and most of them are quite easy to find on google if you just look over the list of which papers were presented each year. This paper is one that I highly recommend. It teaches you, step by step, how to stack monads (using transformers) to develop a nice fully featured evaluator: http://user.cs.tu-berlin.de/~magr/pub/Transformers.en.html If you scroll down a bit this page links to all lists of papers presented at each ICFP: http://www.icfpconference.org/ Just go over that list and see
[Haskell-cafe] Re: Who takes care of Haskell mailing lists?
On Wed, 27 May 2009 17:52:17 -0300, Mauricio briqueabra...@yahoo.com wrote: I would like to create a mailing list for Portuguese speaking Haskell programmers. I tried checking haskell.org mailing lists page, but the only contact e-mail I see is 'mail...@haskell.org', and a message sent to that address is replied with an automatic message saying I'm not authorized to use it. Is there someone I could contact about that? According to Mailing lists - HaskellWiki (see http://haskell.org/haskellwiki/Mailing_lists), Any problems with haskell or haskell-cafe should be reported to haskell-ad...@haskell.org, and any problems with haskell-beginners should be reported to dekudekup...@yahoo.com. In addition, if you wish to suggest a new mailing list for Haskell, I would suggest first posting a message suggesting this idea on the Haskell mailing list (see Haskell Info Page at http://www.haskell.org/mailman/listinfo/haskell), and then moving the topic after the first few posting rounds to the Haskell-Cafe mailing list (this list). Furthermore, there is a list of haskell.org mailing lists at the following site: haskell.org Mailing Lists http://haskell.org/mailman/listinfo It may help to notice that one of the mailing lists listed at the above-mentioned site is the following one for French readers: Haskell-fr Info Page http://www.haskell.org/mailman/listinfo/haskell-fr You may wish to use the existence of this list as a basis for arguing that a Portuguese mailing list should be created. Alternatively, there is the option of creating a Haskell-related mailing list outside of haskell.org, such as the following: haskell-art Info Page http://lists.lurk.org/mailman/listinfo/haskell-art Hope this helps. -- Benjamin L. Russell -- Benjamin L. Russell / DekuDekuplex at Yahoo dot com http://dekudekuplex.wordpress.com/ Translator/Interpreter / Mobile: +011 81 80-3603-6725 Furuike ya, kawazu tobikomu mizu no oto. -- Matsuo Basho^ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Template Haskell very wordy w/r/t Decs and Types
You already have splicing for top level decls. Splicing for local decls is a whole different ball game because it brings new *binders* into scope. For example f = ...g... g = let $(foo) in ...f... Is the 'f' inside 'g' the same 'f' as the one bound at top level? Not necessarily, because $(foo) might bind f. So I can't even do dependency analysis to figure out whether f and g are mutually recursive! It gets harder if $(foo) mentions 'f'; and if the definition of 'f' has a declaration splice too. So splicing local decls introduces a new raft of questions whose answers are not obvious, and that might require some substantial structural rearrangement of GHC. In particular to the rename and then typecheck strategy. It's very similar to reason that we don't allow splices in patterns. Bottom line: my nose tells me this is a swamp and I'm steering clear of it for now. Simon From: Matt Morrow [mailto:moonpa...@gmail.com] Sent: 28 May 2009 00:08 To: Simon Peyton-Jones Cc: Ross Mellgren; Haskell Cafe; GHC users Subject: Re: [Haskell-cafe] Template Haskell very wordy w/r/t Decs and Types Spectacular! How difficult would it be to implement splicing in decls? I'm interested in having a go at it, and it seems like a perfect time since I can cheat off the fresh diff. In particular I'd love to be able to do stuff like this (without the current vicious hackery i'm using) (and granted, where i'm splicing is somewhat willy-nilly, but some approximation of this): - {-# LANGUAGE TemplateHaskell, QuasiQuotes #-} module DecTest where import HsDec import Data.List import DecTestBoot import Language.Haskell.TH.Lib import Language.Haskell.TH.Syntax import Language.Haskell.Meta.Utils bootQ :: Q [Dec] bootQ = bootQFunct primQStruct primQStruct = (''[] ,(conT ''[] `appT`) ,[|[]|] ,[|null|] ,[|undefined|] ,[|union|] ,[|undefined|] ,[|undefined|]) bootQFunct (primN :: Name ,primQ :: TypeQ - TypeQ -- exists q. forall a. a - q a ,emptyQ :: ExpQ -- Q a ,isEmptyQ :: ExpQ -- q a - Bool ,insertQ:: ExpQ -- Int - a - q a - q a ,mergeQ :: ExpQ -- q a - q a - q a ,findMinQ :: ExpQ -- q a - Maybe (Int, a) ,deleteMinQ :: ExpQ) -- q a - q a = do n - newName a let primT = varT primN a = varT n [$dec| data BootQ $(a) = Nil | Node {-# UNPACK #-} !Int $(a) ($(primT) (BootQ $(a))) deriving(Eq,Ord) empty :: BootQ $(a) isEmpty :: BootQ $(a) - Bool insert:: Int - $(a) - BootQ $(a) - BootQ $(a) merge :: BootQ $(a) - BootQ $(a) - BootQ $(a) findMin :: BootQ $(a) - Maybe (Int, $(a)) deleteMin :: BootQ $(a) - BootQ $(a) empty = Nil isEmpty Nil = True isEmpty _ = False findMin Nil = Nothing findMin (Node n x _) = Just (n, x) insert n x q = merge (Node n x $(emptyQ)) q merge (Node n1 x1 q1) (Node n2 x2 q2) | n1 = n2 = Node n1 x1 ($(insertQ) n2 (Node n2 x2 q2) q1) | otherwise = Node n2 x2 ($(insertQ) n1 (Node n1 x1 q1) q2) merge Nil q = q merge q Nil = q deleteMin Nil = Nil deleteMin (Node _ _ q) = case $(findMinQ) q of Nothing - Nil Just (_, Node m y q1) - let q2 = $(deleteMinQ) q in Node m y ($(mergeQ) q1 q2) |] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] About the lazy pattern
张旭 stircrazyn...@hotmail.com writes: Hi, I am really new to haskell. I am reading A gentle instruction to haskell now. And I just cannot understand the chapter below. Is there anybody who can gives me some hints about why the pattern matching for client is so early? How does the pattern matching works here? Reading this thread, it occurs to me that I've probably never used a lazy pattern in my code. So if you, in spite of the helpful replies you've got, still have problems understanding lazy patterns, it may be an option to simply skip this part of the tutorial for now. (Not that I recommend learning Haskell half-way, mind you, but it did work for me :-) -k -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Bool as type class to serve EDSLs.
You are absolutely right about the tantalising opportunity. I know that Lennart has thought quite a bit about this very point when designing his Paradise system. Likewise Conal for Pan. One difficulty is, I think, that it's easy to get ambiguity. Eg ifthenelse (a b) e1 e2 The (ab) produces a boolean-thing, and ifthenelse consumes it; but which type of boolean? The Expr type? Real Bools? Or what? If there was a nice design, then GHC's existing -fno-implicit-prelude flag could be extended (again) to desugar if-then-else to the new thing. But the design is unclear, to me anyway. Simon | -Original Message- | From: haskell-cafe-boun...@haskell.org [mailto:haskell-cafe-boun...@haskell.org] On | Behalf Of Sebastiaan Visser | Sent: 27 May 2009 13:32 | To: Haskell Cafe | Subject: [Haskell-cafe] Bool as type class to serve EDSLs. | | Hello, | | While playing with embedded domain specific languages in Haskell I | discovered the Num type class is a really neat tool. Take this simple | example embedded language that can embed primitives from the output | language and can do function application. | | data Expr :: * - * where |Prim :: String - Expr a |App :: Expr (a - b) - Expr a - Expr b | | Take these two dummy types to represent things in the output language. | | data MyNum | data MyBool | | Now it is very easy to create an Num instance for this language: | | primPlus :: Expr (MyNum - MyNum - MyNum) | primPlus = Prim prim+ | | instance Num (Epxr MyNum) where |a + b = primPlus `App` a `App` b |fromInteger = Prim . show |... | | Which allows you to create very beautiful expression for your language | embedded inside Haskell. The Haskell expression `10 * 5 + 2' produces | a nice and well typed expression in your embedded domain. | | But unfortunately, not everyone in the Prelude is as tolerant as the | Num instance. Take the Eq and the Ord type classes for example, they | require you to deliver real Haskell `Bool's. This makes it impossible | make your DSL an instance of these two, because there are no `Bool's | only `Expr Bool's. | | Which brings me to the point that, for the sake of embedding other | languages, Haskell's Prelude (or an alternative) can greatly benefit | from (at least) a Boolean type class like this: | | class Boolean a where |ifthenelse :: a - b - b - b -- Not sure about this | representation. |... | | And one instance: | | instance Boolean (Expr MyBool) where |ifthenelse c a b = Prim if-then-else `App` c `App` a `App` b | | Now we can change (for example) the Eq type class to this: | | class Eq a where |(==) :: Boolean b = a - a - b |(/=) :: Boolean b = a - a - b | | For which we can give an implementation for our domain: | | primEq :: Epxr (a - a - MyBool) | primEq = Prim == | | instance Eq (Expr a) where |a == b = primEq `App` a `App` b | | And now we get all functionality from the Prelude that is based on Eq | (like not, , ||, etc) for free in our domain specific language! Off | course there are many, many more examples of things from the standard | libraries that can be generalised in order to serve reuse in EDSLs. | | Anyone already working on such a generalized Prelude? I can imagine | much more domains can benefit from this than my example above. Any | interesting thoughts or pointers related to this subject? | | Gr, | | -- | Sebastiaan Visser | | ___ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: We tried this functional, higher-order stuff with LISP and look what happened...
On Wed, 27 May 2009 11:31:07 -0700, Jason Dusek jason.du...@gmail.com wrote: What can we say to that? I'm well practiced in handling those who reject types outright (Python programmers), those who reject what is too different (C programmers), those who can not live without objects (Java programmers), those who insist we must move everything to message passing (Erlang programmers). It's not too often that I meet an embittered LISP programmer -- one who's well acquainted with a bold and well-supported community of functional programmers whose shooting star soon descended to dig a smoking hole in the ground. Who's to say Haskell (and the more typeful languages in general) do not find themselves in the same situation in just a few years' time? Is avoiding success at all costs really enough? First off, the real meaning of the slogan Avoid success at all costs is actually We want lots of users, but not so many that we can't change anything anymore. According to [1] (see http://research.microsoft.com/en-us/um/people/simonpj/papers/history-of-haskell/history.pdf) (see page 10), The fact that Haskell has, thus far, managed the tension between these two strands of development [as a mature language, and as a laboratory in which to explore advanced language design ideas] is perhaps due to an accidental virtue: Haskell has not become too successful. The trouble with runaway success, such as that of Java, is that you get too many users, and the language becomes bogged down in standards, user groups, and legacy issues. In contrast, the Haskell community is small enough, and agile enough, that it usually not only absorbs language changes but positively welcomes them: it’s like throwing red meat to hyenas. One of the authors of the above-mentioned paper, Simon Peyton-Jones, elaborates in [2] as follows: ... Haskell has a sort of unofficial slogan: avoid success at all costs. I think I mentioned this at a talk I gave about Haskell a few years back and it’s become sort of a little saying. When you become too well known, or too widely used and too successful (and certainly being adopted by Microsoft means such a thing), suddenly you can’t change anything anymore. You get caught and spend ages talking about things that have nothing to do with the research side of things. I’m primarily a programming language researcher, so the fact that Haskell has up to now been used for just university types has been ideal. Now it’s used a lot in industry but typically by people who are generally flexible, and they are a generally a self selected rather bright group. What that means is that we could change the language and they wouldn’t complain. Now, however, they’re starting to complain if their libraries don’t work, which means that we’re beginning to get caught in the trap of being too successful. Haskell has a sort of unofficial slogan: avoid success at all costs What I’m really trying to say is that the fact Haskell hasn’t become a real mainstream programming language, used by millions of developers, has allowed us to become much more nimble, and from a research point of view, that’s great. We have lots of users so we get lots of experience from them. What you want is to have a lot of users but not too many from a research point of view -- hence the avoid success at all costs. What makes you think that Haskell is likely eventually to dig a smoking hole in the ground? -- Benjamin L. Russell [1] Hudak, Paul, Hughes, John, Peyton Jones, Simon, and Wadler, Philip. A History of Haskell: Being Lazy With Class. San Diego, California: _The Third ACM SIGPLAN History of Programming Languages Conference (HOPL-III)_ (2007): 12-1 - 12-55, 2007. http://research.microsoft.com/en-us/um/people/simonpj/papers/history-of-haskell/history.pdf [2] Hamilton, Naomi. The A-Z of Programming Languages: Haskell. _Computerworld_. 19 September 2008. 28 May 2009. http://www.computerworld.com.au/article/261007/-z_programming_languages_haskell?pp=10 -- Benjamin L. Russell / DekuDekuplex at Yahoo dot com http://dekudekuplex.wordpress.com/ Translator/Interpreter / Mobile: +011 81 80-3603-6725 Furuike ya, kawazu tobikomu mizu no oto. -- Matsuo Basho^ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Bool as type class to serve EDSLs.
There are multiple possible classes that you might want under different circumstances (I think the most interesting issue is whether the class (==), () etc is in has a fundep from the type of the thing being compared to the type of the boolean), but if NoImplicitPrelude (or some other extension) just desugars if-then-else into ifthenelse (with a default implementation of ifthenelse somewhere) I think that would be enough. Of course once you've got ifthenelse you find yourself wanting explicit desugaring of pattern matching (could view patterns help here?), recursion (into an explicit use of fix), etc... Cheers, Ganesh Simon Peyton-Jones wrote: You are absolutely right about the tantalising opportunity. I know that Lennart has thought quite a bit about this very point when designing his Paradise system. Likewise Conal for Pan. One difficulty is, I think, that it's easy to get ambiguity. Eg ifthenelse (a b) e1 e2 The (ab) produces a boolean-thing, and ifthenelse consumes it; but which type of boolean? The Expr type? Real Bools? Or what? If there was a nice design, then GHC's existing -fno-implicit-prelude flag could be extended (again) to desugar if-then-else to the new thing. But the design is unclear, to me anyway. Simon -Original Message- From: haskell-cafe-boun...@haskell.org [mailto:haskell-cafe-boun...@haskell.org] On Behalf Of Sebastiaan Visser Sent: 27 May 2009 13:32 To: Haskell Cafe Subject: [Haskell-cafe] Bool as type class to serve EDSLs. Hello, While playing with embedded domain specific languages in Haskell I discovered the Num type class is a really neat tool. Take this simple example embedded language that can embed primitives from the output language and can do function application. data Expr :: * - * where Prim :: String - Expr a App :: Expr (a - b) - Expr a - Expr b Take these two dummy types to represent things in the output language. data MyNum data MyBool Now it is very easy to create an Num instance for this language: primPlus :: Expr (MyNum - MyNum - MyNum) primPlus = Prim prim+ instance Num (Epxr MyNum) where a + b = primPlus `App` a `App` b fromInteger = Prim . show ... Which allows you to create very beautiful expression for your language embedded inside Haskell. The Haskell expression `10 * 5 + 2' produces a nice and well typed expression in your embedded domain. But unfortunately, not everyone in the Prelude is as tolerant as the Num instance. Take the Eq and the Ord type classes for example, they require you to deliver real Haskell `Bool's. This makes it impossible make your DSL an instance of these two, because there are no `Bool's only `Expr Bool's. Which brings me to the point that, for the sake of embedding other languages, Haskell's Prelude (or an alternative) can greatly benefit from (at least) a Boolean type class like this: class Boolean a where ifthenelse :: a - b - b - b -- Not sure about this representation. ... And one instance: instance Boolean (Expr MyBool) whereifthenelse c a b = Prim if-then-else `App` c `App` a `App` b Now we can change (for example) the Eq type class to this: class Eq a where (==) :: Boolean b = a - a - b (/=) :: Boolean b = a - a - b For which we can give an implementation for our domain: primEq :: Epxr (a - a - MyBool) primEq = Prim == instance Eq (Expr a) where a == b = primEq `App` a `App` b And now we get all functionality from the Prelude that is based on Eq (like not, , ||, etc) for free in our domain specific language! Off course there are many, many more examples of things from the standard libraries that can be generalised in order to serve reuse in EDSLs. Anyone already working on such a generalized Prelude? I can imagine much more domains can benefit from this than my example above. Any interesting thoughts or pointers related to this subject? Gr, -- Sebastiaan Visser ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe === Please access the attached hyperlink for an important electronic communications disclaimer: http://www.credit-suisse.com/legal/en/disclaimer_email_ib.html === ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Bool as type class to serve EDSLs.
Here's what I usually use. As Simon points out, ambiguity is lurking as soon as you use conditional. You can avoid it a fundep, but that's not necessarily what you want either. -- | Generalization of the 'Bool' type. Used by the generalized 'Eq' and 'Ord'. class Boolean bool where () :: bool - bool - bool -- ^Logical conjunction. (||) :: bool - bool - bool -- ^Logical disjunction. not :: bool - bool -- ^Locical negation. false :: bool -- ^Truth. true :: bool -- ^Falsity. fromBool :: Bool - bool-- ^Convert a 'Bool' to the generalized Boolean type. fromBool b = if b then true else false -- | Generalization of the @if@ construct. class (Boolean bool) = Conditional bool a where conditional :: bool - a - a - a -- ^Pick the first argument if the 'Boolean' value is true, otherwise the second argument. class (Boolean bool) = Eq a bool {- x | a - bool -} where (==) :: a - a - bool (/=) :: a - a - bool x /= y = not (x == y) x == y = not (x /= y) On Thu, May 28, 2009 at 8:14 AM, Simon Peyton-Jones simo...@microsoft.com wrote: You are absolutely right about the tantalising opportunity. I know that Lennart has thought quite a bit about this very point when designing his Paradise system. Likewise Conal for Pan. One difficulty is, I think, that it's easy to get ambiguity. Eg ifthenelse (a b) e1 e2 The (ab) produces a boolean-thing, and ifthenelse consumes it; but which type of boolean? The Expr type? Real Bools? Or what? If there was a nice design, then GHC's existing -fno-implicit-prelude flag could be extended (again) to desugar if-then-else to the new thing. But the design is unclear, to me anyway. Simon | -Original Message- | From: haskell-cafe-boun...@haskell.org [mailto:haskell-cafe-boun...@haskell.org] On | Behalf Of Sebastiaan Visser | Sent: 27 May 2009 13:32 | To: Haskell Cafe | Subject: [Haskell-cafe] Bool as type class to serve EDSLs. | | Hello, | | While playing with embedded domain specific languages in Haskell I | discovered the Num type class is a really neat tool. Take this simple | example embedded language that can embed primitives from the output | language and can do function application. | | data Expr :: * - * where | Prim :: String - Expr a | App :: Expr (a - b) - Expr a - Expr b | | Take these two dummy types to represent things in the output language. | | data MyNum | data MyBool | | Now it is very easy to create an Num instance for this language: | | primPlus :: Expr (MyNum - MyNum - MyNum) | primPlus = Prim prim+ | | instance Num (Epxr MyNum) where | a + b = primPlus `App` a `App` b | fromInteger = Prim . show | ... | | Which allows you to create very beautiful expression for your language | embedded inside Haskell. The Haskell expression `10 * 5 + 2' produces | a nice and well typed expression in your embedded domain. | | But unfortunately, not everyone in the Prelude is as tolerant as the | Num instance. Take the Eq and the Ord type classes for example, they | require you to deliver real Haskell `Bool's. This makes it impossible | make your DSL an instance of these two, because there are no `Bool's | only `Expr Bool's. | | Which brings me to the point that, for the sake of embedding other | languages, Haskell's Prelude (or an alternative) can greatly benefit | from (at least) a Boolean type class like this: | | class Boolean a where | ifthenelse :: a - b - b - b -- Not sure about this | representation. | ... | | And one instance: | | instance Boolean (Expr MyBool) where | ifthenelse c a b = Prim if-then-else `App` c `App` a `App` b | | Now we can change (for example) the Eq type class to this: | | class Eq a where | (==) :: Boolean b = a - a - b | (/=) :: Boolean b = a - a - b | | For which we can give an implementation for our domain: | | primEq :: Epxr (a - a - MyBool) | primEq = Prim == | | instance Eq (Expr a) where | a == b = primEq `App` a `App` b | | And now we get all functionality from the Prelude that is based on Eq | (like not, , ||, etc) for free in our domain specific language! Off | course there are many, many more examples of things from the standard | libraries that can be generalised in order to serve reuse in EDSLs. | | Anyone already working on such a generalized Prelude? I can imagine | much more domains can benefit from this than my example above. Any | interesting thoughts or pointers related to this subject? | | Gr, | | -- | Sebastiaan Visser | | ___ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: What's the problem with iota's type signature?
michael rice nowgate at yahoo.com writes: I've been digging into this stuff for months and it's still tripping me up. For exploration use GHCi. It can tell you the type of thing you have written. It has command to tell you type of thing, the :t. See here: Prelude let double x = Just (x + x) Prelude :t double double :: (Num a) = a - Maybe a Prelude let iota n = [1..n] Prelude :t iota iota :: (Num t, Enum t) = t - [t] Prelude [3,4,5] = iota [1,2,3,1,2,3,4,1,2,3,4,5] You don't have to guess then, Haskell compiler can do the guessing for you. It is called type inference. -- Gracjan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Error message reform (was: Strange type error with associated type synonyms)
One user's view of error message history, perhaps helpful to reformers:-) Once upon a time, Hugs tended to have better error messages than GHC. They still weren't perfect, mostly when begginners where confronted with messages referring to advanced concepts - eg, Simon Thompson had a list of translations of the kind if Hugs reports this, it most likely means that, especially targetted to beginners in his courses, ie users who where unlikely to want things like 'Num (a-b)' instances, or find non-existing semicolons. (the advice to focus on the error location usually means that either the error message is misleading or too difficult for the user to interpret - it is a standard fallback in all programming language implementations, but no more than that; if we rely on it too often, the messages aren't doing their job) Even for more advanced users, it was helpful to get messages from several implementations (at least Hugs and GHC) for tricky cases, just to get different views from which to piece together a picture. This, sadly, is not as well supported these days as it used to be, but getting multiple opinions on type errors is still useful advice (if your code can be handled by multiple implementations, or if a single implementation can offer multiple views, eg, beginner/advanced or top-down/bottom-up or ..). Then Simon PJ invested a lot of energy into improving GHC's error messages, so the balance changed. Error message complaints didn't stop, though, and the error messages were improved further, with more text, and suggestions for possible fixes, etc. The suggestions are sometimes misleading, and I've felt there has been too much weight on narrative text, to the exclusion of actual type information (it is a programming language, after all, so why don't the error messages give type signatures for context instead of trying to talk me through it in natural language, without further references to types!-), but discussions like the present show that Simon has been on the right track with that, for many users. Still, I would really like a just the facts, please mode for GHC, with less text and more type signatures (especially for the contexts of type mismatches). Error messages simply not including the information I need has become my main issue with GHC messages, and seems to be a common thread over many tickets and threads apparently discussing phrasing (eg, expected/inferred: who expects and why, and what is the inference based on?). Somewhere in between, much research has focussed on type errors, and how to report them in general, and implementations like Helium have set out to target beginners with simpler error messages. (*) As for fixes, concrete suggestions are most likely to be adopted, but sometimes it just isn't clear how to improve the situation, and sometimes, there is no single best solution (which has spawned countless interesting papers on type-error reporting;-). It you want to help, file tickets for messages you find unhelpful, and make suggestions for possible improvements. Unfortunately, there doesn't seem to be an error message component in GHC's trac, so querying for relevant tickets is not straightforward. Simon keeps a partial list of error message related tickets here (keeping track of trac tickets - meta-trac?-): http://hackage.haskell.org/trac/ghc/wiki/Status/SLPJ-Tickets Just, please, keep in mind that there is no one-size-fits-all: improving a message for one group of users might well make it less useful for another group. Claus (*) A beginner mode for Haskell systems has often been suggested, even before Helium. Instead, error messages, and even language design decisions have been constrained by trying to serve everyone with a single mode. I'd have thought that Helium, and Dr Scheme, have sufficiently demonstrated the value of having separate levels of a language and the corresponding error messages. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Lazy Parsing
Henning Thielemann schlepp...@henning-thielemann.de wrote: I don't think that it is in general possible to use the same parser for lazy and strict parsing, just because of the handling of parser failure. Polyparse demonstrates that you can mix-and-match lazy parsers with strict parsers in the different parts of a grammar (by choosing whether to use applicative or monadic style). You can also switch between lazy or strict interpretations of the applicative parts of your grammar (by changing the import that decides which version of the parser primitives is in scope). I also used polyparse for lazy parsing, but I found it unintuitive how to make a parser lazy. It can certainly be tricky, and requires a certain amount of experimentation. I think the difficulties are mainly due to the mix of lazy (applicative) and strict (monadic) styles in different non-terminals. A parser that you intend to be lazy, may turn out to be stricter than you hope, because of the strictness of another parser that it depends upon. Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Type class context propagation investigation[MESSAGE NOT SCANNED]
Thanks. GHC at one stage suggested I add (Num a) = to my Num instance (after I'd added (Eq a) = to my Eq instance) and I didn't make the connection. -Original Message- From: Ryan Ingram [mailto:ryani.s...@gmail.com] Sent: Thu 28/05/2009 01:18 To: Paul Keir Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Type class context propagation investigation[MESSAGE NOT SCANNED] Think of classes like data declarations; an instance with no context is a constant, and one with context is a function. Here's a simple translation of your code into data; this is very similar to the implementation used by GHC for typeclasses: data EqDict a = EqDict { eq :: a - a - Bool } data ShowDict a = ShowDict { show :: a - String } data NumDict a = NumDict { num_eq :: EqDict a, num_show :: ShowDict a, plus :: a - a - a } The goal of the compiler is to turn your instance declarations into these structures automatically. Here's a translation of your original instance: eq_foo :: EqDict (Foo a) eq_foo = EqDict { eq = undefined } show_foo :: ShowDict (Foo a) show_foo = ShowDict { show = undefined } num_foo :: NumDict (Foo a) num_foo = NumDict { num_eq = eq_foo, num_show = show_foo, plus = undefined } Now if you add a constraint on the Eq instance, this means that eq from eq_foo might refer to eq in the dictionary for a. How do we get that dictionary? We just pass it as an argument! eq_foo :: EqDict a - EqDict (Foo a) eq_foo eq_a = EqDict { eq = undefined } However, you don't have a similar constraint on the Num instance: num_foo :: NumDict (Foo a) num_foo = NumDict { num_eq = eq_foo something, num_show = show_foo, plus = undefined } The compiler wants to fill in something, but it can't; it doesn't have a dictionary of the type EqDict a. So it tells you so, saying that Eq a is missing! Once you add the (Eq a) constraint to the Num instance, it works: num_foo :: EqDict a - NumDict (Foo a) num_foo eq_a = NumDict { num_eq = eq_foo eq_a, num_show = show_foo, plus = undefined } You can also add a (Num a) constraint instead, and the compiler can use it to get the Eq instance out: num_foo :: NumDict a - NumDict (Foo a) num_foo num_a = NumDict { num_eq = eq_foo (num_eq num_a), num_show = show_foo, plus = undefined } Of course, I'm glossing over the interesting details of the search, but the basic idea is to attempt to fill in the blanks in these definitions. -- ryan On Wed, May 27, 2009 at 2:10 PM, Paul Keir pk...@dcs.gla.ac.uk wrote: Hi, How does the context of a class instance declaration affect its subclasses? The Num class instance outlined below has its requirement for Eq and Show satisfied on the preceding lines, and the code will compile. But if I, say, add an (Eq a) constraint to the Eq instance, in preparation for a simple (==) definition, I find that the Num instance declaration is left lacking. If I add the same (Eq a) constraint now to Num, calm is restored. data Foo a = F a instance Eq (Foo a) where (==) = undefined instance Show (Foo a) where show = undefined instance Num (Foo a) (+) = undefined ... etc. The thing that confuses me with this is that it seems like Num knows that an (Eq a) context has been applied, and so what it sees as a problem, is somehow also the solution. Any advice/rules of thumb? Does this situation occur elsewhere? How do these constraints propagate? Thanks, Paul ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Bool as type class to serve EDSLs.
Of course once you've got ifthenelse you find yourself wanting explicit desugaring of pattern matching (could view patterns help here?), Could you be more specific about what you want there, perhaps with a small example? I recognize the other problems from my own forays into EDSLs, but I'm not sure I recognize this one. If you want to reuse the existing 'lhs=rhs' syntax for patterns specific to your EDSL, both QuasiQuotes and ViewPatterns might help, if you want to be able to compose patterns beyond the limitations of that syntax, one of the proposals and libraries for first-class patterns might help, adding functionality at the expense of more complex syntax. recursion (into an explicit use of fix), etc... Yes, in principle (you're thinking of sharing, and of lifting pure code?). In practice, too much machinery is attached to the existing 'let' to make that likely. But this reminds me of another closely related issue: GHC offers a lot of help in moving stuff from compiler-baked-in to library-provided, but almost none of the mechanisms works at the level of syntax/AST (where most other languages do their meta-programming/language extension support). RULES and compiler plugins work on core, where it is too late to do EDSL-specific source-level rewrites, TH requires quoted things to parse and type-check in the un-extended language, making it less useful for EDSL-specific language extensions. For instance, think of the arrows syntax: there doesn't seem to be any way that this could have been defined in a library, so it had to be baked into GHC? QuasiQuotes seem to be the only feature that gives source-level control, and they suffer from the lack of easily available parsers (eg, if my EDSL requires an extension of some Haskell construct, I'd like to be able to reuse the Haskell parsers for the baseline). There is a package on hackage targetting that issue (haskell-src-meta), but it relies on a second frontend (haskell-src-ext), and only works with a single GHC version. Claus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: What's the problem with iota's type signature?
On Thu, May 28, 2009 at 5:19 PM, Gracjan Polak gracjanpo...@gmail.com wrote: You don't have to guess then, Haskell compiler can do the guessing for you. It isn't guess, Haskell compiler (like GHC) gets these types by (type) inference, as you said :-) lee It is called type inference. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] the problem of design by negation
On Thu, May 28, 2009 at 5:59 AM, Conal Elliott co...@conal.net wrote: Thanks for bringing in this angle, David. My preference is for honest and humble practice and documentation of negative design. Instead of saying that something won't work, can't work, is impossible etc (or rephrased via must, only, etc), I'd like honest admissions like I couldn't figure out X, I got stuck on Y, etc. After all, someone else might get further. Or, in the rare cases, when something actually is impossible, say so prove it. Yes, this angle is important, escpecially if you like me read a lot of code and end up thinking why is this code so complicated, there must be an easier way. I often feel that thinking like that prevents quick understanding of the code, simply because my brain is pre-occupied with solving the problem more elegantly while trying to understand what is going on :-) Often a particular solution isn't impossible to use (i.e. the words can't, won't etc shouldn't be used), instead solutions aren't as good as others when resource constraints into account. Of course the negative reasons must be backed up with data (sometimes rough estimates are enough), but this brings me to other pet peeves of mine at work, the general lack of non-functional requirements and prototyping with performance tests. /M -- Magnus Therning(OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus@therning.org http://therning.org/magnus identi.ca|twitter: magthe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] About the lazy pattern
Hi Ryan, thanks for a nice and thorough explanation. I had trouble understanding the section of the tutorial as well. Maybe it would deserve to rewrite to something a bit simpler? Anyhow, I'd like to ask: Is there a reason for which pattern matching for single-constructor data types isn't lazy by default? For example, why do I have to write weird ~(x,y) = (1,x) crazy = weird crazy when the compiler knows that the type (x,y) has just the single constructor, and could automatically introduce the additional laziness without any risk? Petr Hi nemo. I had a lot of trouble with that section of the tutorial as well, and I believe that once you get it, a lot of Haskell becomes a lot simpler. The way I eventually figured it out is using this idealized execution model for Haskell: you just work by rewriting the left side of a function to its right side. The only question is figuring out *which* function to rewrite! Here's a simpler example: f 0 = 0 f x = x+1 g (x:xs) = error urk g [] = 2 const a b = a ex1 = const (f 1) (g [2,3]) ex2 = f (const (g []) (g [1,2])) Lets say you wanted to know the value of ex1; you just use rewriting ex1 -- rewrite using ex1 = const (f 1) (g [2,3]) -- rewrite using const = f 1 -- rewrite using f (second pattern) = 1+1 -- rewrite using + = 2 But lets say we picked a different order to rewrite... ex1 -- rewrite using ex1 = const (f 1) (g [2,3]) -- rewrite using g = const (f 1) (error urk) -- rewrite using error computation stops Of course this is bad, and it was obviously wrong to evaluate g first (because const is lazy). So one heuristic we always use is rewrite the leftmost application first which avoids this problem. But lets try that rule on ex2! ex2 -- rewrite using ex2 = f (const (g []) (g [1,2])) -- rewrite using f = ? Unfortunately, now we don't know which pattern to match! So we have to pick a different thing to rewrite. The next rule is that, if the thing you want to rewrite has a pattern match, look at the argument for the patterns being matched and rewrite them instead, using the same leftmost first rule: f (const (g []) (g [1,2])) -- trying to pattern match f's first argument -- rewrite using const = f (g []) -- still pattern matching -- rewrite using g = f 2 -- now we can match -- rewrite using f (second pattern) = 2+1 -- rewrite using + = 3 So, back to the original question (I'm rewriting the arguments to client and server for clarity) reqs = client init resps resps = server reqs client v (rsp:rsps) = v : client (next rsp) rsps server (rq:rqs) = process rq : server rqs Lets say we are trying to figure out the value of resps, to print all the responses to the screen: resps -- rewrite using resps = server reqs -- pattern match in server -- rewrite reqs = server (client init resps) -- pattern match in server -- pattern match also in client -- rewrite using resps = server (client init (server reqs)) -- pattern match in server, client, then server -- rewrite using reqs = server (client init (server (client init resps))) You see that we are in a loop now; we are stuck trying to pattern match and we will never make any progress! The lazy pattern says trust me, this pattern will match, you can call me on it later if it doesn't! reqs = client init resps resps = server reqs client v (rsp:rsps) = v : client (next rsp) rsps server (rq:rqs) = process rq : server rqs resps -- rewrite resps = server reqs -- server wants to pattern match, rewrite reqs = server (client init resps) -- Now, the lazy pattern match says this will match, wait until later -- rewrite using client! = let (rsp:rsps) = resps in server (init : client (next rq) rqs) -- rewrite using server = let (rsp:rsps) = resps in process init : server (client (next rq) rqs) We now have a list node, so we can print the first element and continue (which requires us to know the code for process and next, but you get the idea, I hope!) Now of course, you can lie to the pattern matcher: next x = x + 1 init = 5 client init [] -- rewrite using client = let (rsp0:rsps0) = [] in init : client (next rsp0) rsps0 -- rewrite using init = let (rsp0:rsps0) = [] in 5 : client (next rsp0) rsps0 -- print 5 and continue to evaluate... let (rsp0:rsps0) = [] in client (next rsp0) rsps0 -- rewrite using client = let (rsp0:rsps0) = [] (rsp1:rsps1) = rsps0 in (next rsp0) : client (next rsp1) rsps1 -- rewrite using next = let (rsp0:rsps0) = [] (rsp1:rsps1) = rsps0 in rsp0+1 : client (next rsp1) rsps1 -- + wants to pattern match on its first argument -- rewrite using rsp0 computation stops, pattern match failure, (rsp0:rsps0) does not match [] For this reason, many people (myself included) consider it bad style to use lazy/irrefutable pattern matches on data types with more than one constructure. But
Re: [Haskell-cafe] About the lazy pattern
2009/5/28 Petr Pudlak d...@pudlak.name: Hi Ryan, thanks for a nice and thorough explanation. I had trouble understanding the section of the tutorial as well. Maybe it would deserve to rewrite to something a bit simpler? Anyhow, I'd like to ask: Is there a reason for which pattern matching for single-constructor data types isn't lazy by default? For example, why do I have to write weird ~(x,y) = (1,x) crazy = weird crazy when the compiler knows that the type (x,y) has just the single constructor, and could automatically introduce the additional laziness without any risk? I think this is really two questions: 1) Why can't the /compiler/ add extra laziness automatically? Because it's not semantics preserving: weird (x, y) = (1, x) lazyWeird ~(x, y) = (1, x) weird undefined = undefined lazyWeird undefined = (1, undefined) Of course, it's arguable as to whether turning non-terminating programs into terminating ones is really that big of a deal. In fact, some transformations in GHC already make this kind of change for optimization purposes (albeit only to things of function type, where the waters are murkier). Even if it were semantics preserving, making things MORE lazy is not likely to lead to performance improvement, so I doubt the compiler would want to do this. 2) Why isn't product pattern matching lazy by default in Haskell? I can't give a definitive answer, but I suspect that the reason is that the Haskell design team didn't want adding an extra constructor to your type definition to change the semantics of all the pattern matches in your program. Seems pretty sensible to me :-) Cheers, Max ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Data.Binary and little endian encoding
On Thursday 28 of May 2009 07:52:56 David Leimbach wrote: Sorry took so long to get back... Thank you for the response. Been really busy lately :-) There are also a lot of 9P implementations in many languages that you can interoperate with: http://9p.cat-v.org/implementations Thank you for that link. I didn't find it earlier. But actually I asked what are you trying to write? -- Khudyakov Alexey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Bool as type class to serve EDSLs.
Or overloading the `whitespace operator' for several kinds of application. On May 28, 2009, at 9:50 AM, Augustsson, Lennart wrote: And explicit desugaring of list syntax. -Original Message- From: Sittampalam, Ganesh [mailto:ganesh.sittampa...@credit- suisse.com] Sent: 28 May 2009 08:46 To: Simon Peyton-Jones; Sebastiaan Visser; Haskell Cafe Cc: Augustsson, Lennart Subject: RE: [Haskell-cafe] Bool as type class to serve EDSLs. There are multiple possible classes that you might want under different circumstances (I think the most interesting issue is whether the class (==), () etc is in has a fundep from the type of the thing being compared to the type of the boolean), but if NoImplicitPrelude (or some other extension) just desugars if-then-else into ifthenelse (with a default implementation of ifthenelse somewhere) I think that would be enough. Of course once you've got ifthenelse you find yourself wanting explicit desugaring of pattern matching (could view patterns help here?), recursion (into an explicit use of fix), etc... Cheers, Ganesh Simon Peyton-Jones wrote: You are absolutely right about the tantalising opportunity. ... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Stack overflow
Krzysztof Skrzętnicki wrote: 2009/5/27 Bertram Felgenhauer bertram.felgenha...@googlemail.com: I wrote: Krzysztof Skrzętnicki wrote: The code for modifying the counter: (\ msg - atomicModifyIORef ioref (\ cnt - (cntMsg cnt msg,( atomicModifyIORef does not force the new value of the IORef. If the previous contents of the IORef is x, the new contents will be a thunk, (\ cnt - (cntMsg cnt msg,())) x Sorry, it's slightly worse than that. The contents becomes sel_0 (\ cnt - (cntMsg cnt msg, ())) x where sel_0 is basically an RTS internal version of fst. Instead of reading the new value of the IORef, you could also force the old one: atomicModifyIORef ioref (\ cnt - (cntMsg cnt msg, msg)) = (return $!) Thanks for the tip, although it seems tricky to get it right. I wonder why there is no strict version of atomicModifyIORef? Something like this? -- | Stricter version of 'atomicModifyIORef', which prevents building -- up huge thunks in the 'IORef' due to repeated modification. -- Unlike 'atomicModifyIORef', 'atomicModifyIORef'' may block. atomicModifyIORef' :: IORef a - (a - (a, b)) - IO b atomicModifyIORef' ioref f = do res - atomicModifyIORef ioref f new - readIORef ioref new `seq` return res (The step that may block is forcing the new value - if another thread is already evaluating part of the thunk, the currently executing thread will block, waiting for the other thread to finish.) Dually there might be a strict version of IORef datatype. One interesting feature of atomicModifyIORef is that its implementation is lock-free, and never blocks (which affects exception handling): replacing the old value by the new value is done with compare-and-swap operation in a tight loop. Each iteration executes very quickly because all it does is replace the reference to the old value in the new thunk. With a strict IORef, the time window between reading the old value and storing the new value would become arbitrarily large, because you'd have to force the new value before exchanging it with the old value. So a reasonable implementation would have to use locks instead, I think, making atomicModifyIORef more expensive, and less useful in contexts that block exceptions. Bertram ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re[2]: [Haskell-cafe] Bool as type class to serve EDSLs.
Hello Lennart, Thursday, May 28, 2009, 11:57:09 AM, you wrote: -- | Generalization of the 'Bool' type. Used by the generalized 'Eq' and 'Ord'. class Boolean bool where () :: bool - bool - bool -- ^Logical conjunction. (||) :: bool - bool - bool -- ^Logical disjunction. i use another approach which imho is somewhat closer to interpretation of logical operations in dynamic languages (lua, ruby, perl): a ||| b | isDefaultValue a = b | otherwise= a a b | isDefaultValue a = defaultValue | otherwise= b -- Class of types having default value: classDefaults a where defaultValue :: a instance Defaults () where defaultValue = () instance Defaults Bool where defaultValue = False instance Defaults [a]where defaultValue = [] instance Defaults (a-a) where defaultValue = id instance Defaults (Maybe a)where defaultValue = Nothing instance Defaults (a-IO a)where defaultValue = return instance Defaults a = Defaults (IO a) where defaultValue = return defaultValue instance Defaults Int where defaultValue = 0 instance Defaults Integer where defaultValue = 0 instance Defaults Double where defaultValue = 0 -- Class of types that can be tested for default value: classTestDefaultValue a where isDefaultValue :: a - Bool instance TestDefaultValue Boolwhere isDefaultValue = not instance TestDefaultValue [a] where isDefaultValue = null instance TestDefaultValue Int where isDefaultValue = (==0) instance TestDefaultValue Integer where isDefaultValue = (==0) instance TestDefaultValue Double where isDefaultValue = (==0) usage examples: return$ (isDir addTrailingPathSeparator) filespec openWebsite$ (isWindows windosifyPath) file let options = (compressionEnabled cvt -m compressionMethod')++ (encryptionEnabledcvt -ae= encryptionMethod')++encryptionOptions++ (protectionEnabledcvt -rr protectionMethod') let another_msg = ciphers ||| not encrypted let msg = ftLocked footer yes ||| no -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Type class context propagation investigation
Thanks Wren, that makes sense. Ryan Ingram wrote: Think of classes like data declarations; an instance with no context is a constant, and one with context is a function. Here's a simple translation of your code into data; this is very similar to the implementation used by GHC for typeclasses: data EqDict a = EqDict { eq :: a - a - Bool } data ShowDict a = ShowDict { show :: a - String } data NumDict a = NumDict { num_eq :: EqDict a, num_show :: ShowDict a, plus :: a - a - a } The goal of the compiler is to turn your instance declarations into these structures automatically. Another way of explaining this, if you're a Curry--Howard fan, is that the compiler is looking for a proof that the type belongs to the class, where = is logical implication. This is very similar to how Prolog searches for proofs, if you're familiar with logic programming. Classes declare the existence of logical predicates, along with the form of what a proof of the predicate looks like. Instances declare a particular proof (or family of proofs if there are free type variables). Thus, the Num class is declared as, class (Eq a, Show a) = Num a where ... which says: for any type |a|, we can prove |Num a| if (and only if) we can prove |Eq a| and |Show a|, and can provide definitions for all the functions in the class using only the assumptions that |Eq a|, |Show a|, and |Num a|. When you declare, instance Eq b = Eq (Foo b) where ... you're providing a proof of |Eq b = Eq (Foo b)|. That is, you can provide a conditional proof of |Eq (Foo b)|, given the assumption that you have a proof of |Eq b|. Notice how the context for instances is subtly different from the context for classes. For instances you're saying that this particular proof happens to make certain assumptions; for classes you're saying that all proofs require these assumptions are valid (that is, providing the functions isn't enough to prove membership in the class). Later on you declare, instance Num (Foo b) where ... but remember that this proof must have the same form as is declared by the class definition. This means that you must have proofs of |Eq (Foo b)| and |Show (Foo b)|. Unfortunately, you don't actually have a proof of |Eq (Foo b)|, you only have a proof of |Eq b = Eq (Foo b)|. In order to use that proof you must add the |Eq b| assumption to this proof as well: instance Eq b = Num (Foo b) where ... When the compiler is complaining about the original one, what it's telling you is that the |Num (Foo b)| proof can never exist because you can never provide it with a proof of |Eq (Foo b)| in order to fulfill its requirements. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Data.Binary and little endian encoding
On Thu, May 28, 2009 at 5:42 AM, Khudyakov Alexey alexey.sklad...@gmail.com wrote: On Thursday 28 of May 2009 07:52:56 David Leimbach wrote: Sorry took so long to get back... Thank you for the response. Been really busy lately :-) There are also a lot of 9P implementations in many languages that you can interoperate with: http://9p.cat-v.org/implementations Thank you for that link. I didn't find it earlier. But actually I asked what are you trying to write? I'm trying to implement the protocol, so that I can implement other things on top of that. I'm also trying to figure out how bad/good Haskell Binary IO really is that it's been addressed a few times differently :-) -- Khudyakov Alexey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Strange type error with associated type synonyms
Bulat Ziganshin bulat.zigans...@gmail.com wrote: Hello Achim, Thursday, May 28, 2009, 1:34:55 AM, you wrote: Error: type of x is Integer while type of read argument should be String The problem with this is that the compiler can't know whether or not the type of arguments to read should be a String, as someone could have messed up read's signature. i don't understood what you mean, can you give an example? Error : type of x is String while the type of an argument to read should be Integer , given that, somewhere, you have read :: Integer - a , which is, of course, wrong, and that's the point. -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] gtk2hs, TreeView and CellRenderer
As far as I can tell, there is not way to create CellRenderer that could include icons with the text (I think it is because of incompatibilities of Haskell type classes and Gtk inheritance hierarchy). Is it a good way to use CellRendererPixbuf and render to pixbufs using Cairo? I think my TreeView hierarchies won't be very big, around 1000 items for a while. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Data.Binary and little endian encoding
leimy2k: I'm also trying to figure out how bad/good Haskell Binary IO really is that it's been addressed a few times differently :-) FWIW Binary IO as implemented in Data.Binary is widely used in our production systems at Galois. I'd be fairly confident in it. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Introducing Instances in GHC point releases
On 27/05/2009 22:02, Henning Thielemann wrote: My proposal is thus: Discourage orphan instances! If you encounter that an instance is missing and it is a canonical one, it should be added to the package that defines the type or the class. If there are several choices for the implementation then the package where the instance would belong to should document that. Then programmers should find a consensus which of the choices they prefer. If you cannot wait for an official adaption of the required instance, then you must work with newtype wrappers. Quite. I argued the no orphan instances in libraries position on the libraries list last year, here's the start of the (longish) thread: http://www.haskell.org/pipermail/libraries/2008-September/010618.html We ought to have a guidelines for API design section of the wiki somewhere, so we could put this in it. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Data.Binary and little endian encoding
I'm trying to implement the protocol, so that I can implement other things on top of that. I'm also trying to figure out how bad/good Haskell Binary IO really is that it's been addressed a few times differently :-) FWIW, I've used Data.Binary extensively and have found it a joy to work with. I've used it to serialize/deserialize ethernet packets in real time for a VPN implementation and have never had a problem. It's quite fast and robust. /jve ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Data.Binary and little endian encoding
On Thursday, May 28, 2009, Don Stewart d...@galois.com wrote: leimy2k: I'm also trying to figure out how bad/good Haskell Binary IO really is that it's been addressed a few times differently :-) FWIW Binary IO as implemented in Data.Binary is widely used in our production systems at Galois. I'd be fairly confident in it. Fair enough. I am just new to the interface, wondering if I should try matching responses by pulling apart via Get, or the bit syntax package. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Introducing Instances in GHC point releases
On Thu, 28 May 2009, Simon Marlow wrote: Quite. I argued the no orphan instances in libraries position on the libraries list last year, here's the start of the (longish) thread: http://www.haskell.org/pipermail/libraries/2008-September/010618.html I remember. What I propose additionally is, that, when orphan instances are banned, we can allow addition of instances with the A.B.* version range just like this is allowed for all other language elements. We ought to have a guidelines for API design section of the wiki somewhere, so we could put this in it. That's currently spread across Category:Style. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Data.Binary and little endian encoding
Fair enough. I am just new to the interface, wondering if I should try matching responses by pulling apart via Get, or the bit syntax package. I'm assming you have some 'data Foo = ...'? If this is the case, you're probably okay writing an instance of Binary for Foo and using encode/decode. That's all I've had to do and had superb performance. /jve ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Error message reform (was: Strange type error with associated type synonyms)
John Dorsey hask...@colquitt.org wrote: As another native English speaker, I found expected/inferred very intuitive when I was new to GHC, and to Haskell. I even think that expected/inferred helped me form my intuition about Haskell's type inference. First off, me too, and I'm not a native speaker. OTOH, while expected is not ambiguous, inferred is: After all, both types are inferred. I opt for expected/encountered -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Data.Binary and little endian encoding
On Thu, 2009-05-28 at 12:08 -0400, John Van Enk wrote: I'm trying to implement the protocol, so that I can implement other things on top of that. I'm also trying to figure out how bad/good Haskell Binary IO really is that it's been addressed a few times differently :-) FWIW, I've used Data.Binary extensively and have found it a joy to work with. I've used it to serialize/deserialize ethernet packets in real time for a VPN implementation and have never had a problem. It's quite fast and robust. Is that code available? We could do with something serious for benchmarking the binary package, especially if we go for any major re-engineering. If it's not available publicly perhaps you might share it privately. Don and I have discussed a few times writing a paper on the design and implementation of a binary library. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Data.Binary and little endian encoding
On Thu, May 28, 2009 at 9:17 AM, John Van Enk vane...@gmail.com wrote: Fair enough. I am just new to the interface, wondering if I should try matching responses by pulling apart via Get, or the bit syntax package. I'm assming you have some 'data Foo = ...'? If this is the case, you're probably okay writing an instance of Binary for Foo and using encode/decode. That's all I've had to do and had superb performance. encode/decode do Big Endian, and 9P does little endian. From the man page: Each message consists of a sequence of bytes. Two–, four–, and eight–byte fields hold unsigned integers represented in little–endian order (least significant byte first). encode/decode just won't work for me as a result, as they assume the not-so-aptly-named (at least in this case) network byte order. Since I'm not Rob Pike, or Ken Thompson or any of the Plan 9 guys, I can't tell you why they chose little endian for this. (I should note that I sometimes work with CAN hardware, and depending on what people want to put on the line, little endian creeps in there too, so this issue will have to be dealt with here as well, if I am to use Data.Binary) I've got (typing from memory, forgive syntax errors) module Nine (Message) where {-- missing imports --} notag = putWord16le -1 -- Message type field values -- from: http://plan9.bell-labs.com/sources/plan9/sys/include/fcall.h tversion = 100 rversion = 101 rerror = 107 -- only 9P2000 is being handled so some constructors are simple data Message = Tversion | Rversion {size :: Int, tag :: Int, msize :: Int, version :: String} | Rerror {message :: String} -- maybe this should be Maybe ByteString? ... instance Binary Message where put Tversion = putWord32le 16 tversion notag msize 9P2000 put Rversion = putWord32le 16 rversion notag msize 9P2000 get = do size - getWord32le tag - getWord8 case tag of rversion - do msize - getWord32le version - getRemainingLazyByteString return (Rversion size tag msize (C.unpack version)) === I'm beginning to feel the Get Monad is not going to be as nice as if I had some bit-syntax for determining what type of return message I'm getting. Any T message can be met with the paired R response, or an Rerror message, with a detailed description of what went wrong. My instance of get is looking like it's going to be pretty nasty :-) The first message in any 9p session is Tversion with Rversion or Rerror response. There's optional authentication hooks via Tauth/Rauth, and then the filesystem namespace navigation operation messages. Dave /jve ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Data.Binary and little endian encoding
leimy2k: encode/decode do Big Endian, and 9P does little endian. From the man page: Each message consists of a sequence of bytes. Two , four , and eight byte fields hold unsigned integers represented in little endian order (least significant byte first). encode/decode just won't work for me as a result, as they assume the not-so-aptly-named (at least in this case) network byte order. Since I'm not Rob Pike, or Ken Thompson or any of the Plan 9 guys, I can't tell you why they chose little endian for this. I think you misunderstand the API: encode and decode *use whatever the underlying instance for your data type uses*. If you write an instance that uses the little endian primitives, that is what I will use. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] About the lazy pattern
The main change I would make is to rename the arguments to client/server; they overload the same names (reqs/resps) as the top level declarations above, so it's very easy to get confused while reading it. Partially, I think this is just a hard concept to understand; struggling to figure it out definitely helped me understand the language in general. One idea is to draw a graph showing the cycle of dependences: client - resps, resps - server, server - reqs, reqs - client, and explaining that we break the dependency cycle in two ways: (1) the init parameter to client allows reqs to output its first message before any processing has done (2) but in order to do so, it needs to be able to delay the pattern match. Perhaps rewrite client first in this way: client init rsps = init : (rest rsps) where rest (r:rs) = client (next r) rs then show the additional syntactic sugar for delaying the pattern match until needed? It also might help to make the example concrete by implementing a simple next and process. -- ryan On Thu, May 28, 2009 at 4:18 AM, Petr Pudlak d...@pudlak.name wrote: Hi Ryan, thanks for a nice and thorough explanation. I had trouble understanding the section of the tutorial as well. Maybe it would deserve to rewrite to something a bit simpler? Anyhow, I'd like to ask: Is there a reason for which pattern matching for single-constructor data types isn't lazy by default? For example, why do I have to write weird ~(x,y) = (1,x) crazy = weird crazy when the compiler knows that the type (x,y) has just the single constructor, and could automatically introduce the additional laziness without any risk? Petr Hi nemo. I had a lot of trouble with that section of the tutorial as well, and I believe that once you get it, a lot of Haskell becomes a lot simpler. The way I eventually figured it out is using this idealized execution model for Haskell: you just work by rewriting the left side of a function to its right side. The only question is figuring out *which* function to rewrite! Here's a simpler example: f 0 = 0 f x = x+1 g (x:xs) = error urk g [] = 2 const a b = a ex1 = const (f 1) (g [2,3]) ex2 = f (const (g []) (g [1,2])) Lets say you wanted to know the value of ex1; you just use rewriting ex1 -- rewrite using ex1 = const (f 1) (g [2,3]) -- rewrite using const = f 1 -- rewrite using f (second pattern) = 1+1 -- rewrite using + = 2 But lets say we picked a different order to rewrite... ex1 -- rewrite using ex1 = const (f 1) (g [2,3]) -- rewrite using g = const (f 1) (error urk) -- rewrite using error computation stops Of course this is bad, and it was obviously wrong to evaluate g first (because const is lazy). So one heuristic we always use is rewrite the leftmost application first which avoids this problem. But lets try that rule on ex2! ex2 -- rewrite using ex2 = f (const (g []) (g [1,2])) -- rewrite using f = ? Unfortunately, now we don't know which pattern to match! So we have to pick a different thing to rewrite. The next rule is that, if the thing you want to rewrite has a pattern match, look at the argument for the patterns being matched and rewrite them instead, using the same leftmost first rule: f (const (g []) (g [1,2])) -- trying to pattern match f's first argument -- rewrite using const = f (g []) -- still pattern matching -- rewrite using g = f 2 -- now we can match -- rewrite using f (second pattern) = 2+1 -- rewrite using + = 3 So, back to the original question (I'm rewriting the arguments to client and server for clarity) reqs = client init resps resps = server reqs client v (rsp:rsps) = v : client (next rsp) rsps server (rq:rqs) = process rq : server rqs Lets say we are trying to figure out the value of resps, to print all the responses to the screen: resps -- rewrite using resps = server reqs -- pattern match in server -- rewrite reqs = server (client init resps) -- pattern match in server -- pattern match also in client -- rewrite using resps = server (client init (server reqs)) -- pattern match in server, client, then server -- rewrite using reqs = server (client init (server (client init resps))) You see that we are in a loop now; we are stuck trying to pattern match and we will never make any progress! The lazy pattern says trust me, this pattern will match, you can call me on it later if it doesn't! reqs = client init resps resps = server reqs client v (rsp:rsps) = v : client (next rsp) rsps server (rq:rqs) = process rq : server rqs resps -- rewrite resps = server reqs -- server wants to pattern match, rewrite reqs = server (client init resps) -- Now, the lazy pattern match says this will match, wait until later -- rewrite using client! = let (rsp:rsps) = resps in server (init : client (next rq) rqs) -- rewrite using server = let (rsp:rsps) = resps in process init : server (client (next rq) rqs) We now
Re: [Haskell-cafe] Data.Binary and little endian encoding
On Thu, May 28, 2009 at 6:34 PM, Duncan Coutts duncan.cou...@worc.ox.ac.ukwrote: If it's not available publicly perhaps you might share it privately. Don and I have discussed a few times writing a paper on the design and implementation of a binary library. I would definitely like to read such a paper. Except for Don's blog entries there's precious little written on the design of high performance Haskell libraries. -- Johan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Data.Binary and little endian encoding
Writing instances encode/decode that use either little endian or big endian (or mixed!) is trivial... see attached file. I don't see where your problem is... On Thu, May 28, 2009 at 12:35 PM, David Leimbach leim...@gmail.com wrote: On Thu, May 28, 2009 at 9:17 AM, John Van Enk vane...@gmail.com wrote: Fair enough. I am just new to the interface, wondering if I should try matching responses by pulling apart via Get, or the bit syntax package. I'm assming you have some 'data Foo = ...'? If this is the case, you're probably okay writing an instance of Binary for Foo and using encode/decode. That's all I've had to do and had superb performance. encode/decode do Big Endian, and 9P does little endian. From the man page: Each message consists of a sequence of bytes. Two–, four–, and eight–byte fields hold unsigned integers represented in little–endian order (least significant byte first). encode/decode just won't work for me as a result, as they assume the not-so-aptly-named (at least in this case) network byte order. Since I'm not Rob Pike, or Ken Thompson or any of the Plan 9 guys, I can't tell you why they chose little endian for this. (I should note that I sometimes work with CAN hardware, and depending on what people want to put on the line, little endian creeps in there too, so this issue will have to be dealt with here as well, if I am to use Data.Binary) I've got (typing from memory, forgive syntax errors) module Nine (Message) where {-- missing imports --} notag = putWord16le -1 -- Message type field values -- from: http://plan9.bell-labs.com/sources/plan9/sys/include/fcall.h tversion = 100 rversion = 101 rerror = 107 -- only 9P2000 is being handled so some constructors are simple data Message = Tversion | Rversion {size :: Int, tag :: Int, msize :: Int, version :: String} | Rerror {message :: String} -- maybe this should be Maybe ByteString? ... instance Binary Message where put Tversion = putWord32le 16 tversion notag msize 9P2000 put Rversion = putWord32le 16 rversion notag msize 9P2000 get = do size - getWord32le tag - getWord8 case tag of rversion - do msize - getWord32le version - getRemainingLazyByteString return (Rversion size tag msize (C.unpack version)) === I'm beginning to feel the Get Monad is not going to be as nice as if I had some bit-syntax for determining what type of return message I'm getting. Any T message can be met with the paired R response, or an Rerror message, with a detailed description of what went wrong. My instance of get is looking like it's going to be pretty nasty :-) The first message in any 9p session is Tversion with Rversion or Rerror response. There's optional authentication hooks via Tauth/Rauth, and then the filesystem namespace navigation operation messages. Dave /jve ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- /jve binaryTest.hs Description: Binary data ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Stack overflow
On Thu, May 28, 2009 at 14:41, Bertram Felgenhauer bertram.felgenha...@googlemail.com wrote: Krzysztof Skrzętnicki wrote: 2009/5/27 Bertram Felgenhauer bertram.felgenha...@googlemail.com: I wrote: Krzysztof Skrzętnicki wrote: The code for modifying the counter: (\ msg - atomicModifyIORef ioref (\ cnt - (cntMsg cnt msg,( atomicModifyIORef does not force the new value of the IORef. If the previous contents of the IORef is x, the new contents will be a thunk, (\ cnt - (cntMsg cnt msg,())) x Sorry, it's slightly worse than that. The contents becomes sel_0 (\ cnt - (cntMsg cnt msg, ())) x where sel_0 is basically an RTS internal version of fst. Instead of reading the new value of the IORef, you could also force the old one: atomicModifyIORef ioref (\ cnt - (cntMsg cnt msg, msg)) = (return $!) Thanks for the tip, although it seems tricky to get it right. I wonder why there is no strict version of atomicModifyIORef? Something like this? -- | Stricter version of 'atomicModifyIORef', which prevents building -- up huge thunks in the 'IORef' due to repeated modification. -- Unlike 'atomicModifyIORef', 'atomicModifyIORef'' may block. atomicModifyIORef' :: IORef a - (a - (a, b)) - IO b atomicModifyIORef' ioref f = do res - atomicModifyIORef ioref f new - readIORef ioref new `seq` return res (The step that may block is forcing the new value - if another thread is already evaluating part of the thunk, the currently executing thread will block, waiting for the other thread to finish.) Dually there might be a strict version of IORef datatype. One interesting feature of atomicModifyIORef is that its implementation is lock-free, and never blocks (which affects exception handling): replacing the old value by the new value is done with compare-and-swap operation in a tight loop. Each iteration executes very quickly because all it does is replace the reference to the old value in the new thunk. With a strict IORef, the time window between reading the old value and storing the new value would become arbitrarily large, because you'd have to force the new value before exchanging it with the old value. So a reasonable implementation would have to use locks instead, I think, making atomicModifyIORef more expensive, and less useful in contexts that block exceptions. We may as well drop the 'atomic' keyword and provide a warning about possible blocking of thread. The end user may forkIO the modification if he wants to. I modified the code as follows, it works now: (\ msg - atomicModifyIORef ioref (\ cnt - (cntMsg cnt msg,cnt)) = (return $!)) Thank you all for your help! Best regards Christopher Skrzętnicki ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] attaching a ghci session to another process
I am starting to get more involved with haskell programming and I'd like to create a program where I can use the interactive loop in ghci to run a haskell functions that create graphics in a separate openGL window. This would be a separate interactive window from the terminal i am running ghci in and have it's own event-loop/thread of execution. For a very simple example, I would have a haskel function called w = window , which when executed would create an openGL window (inside a seprate window manager shell) and return an identifier to it. A call to another fuinction might be obj = cube [..] w whch would draw an cube in the window. etc. The openGL would have it's own event loop running to handle mouse/keyboard and refresh events which means that I would be able to manipuolate the camera with the mouse (pan, zoom, rotate etc.). This would be separate fromt he ghci input loop running in the original terminal window. The graphics part of this is easy for me, I have this implemented in other langauges, but what i would like to do is create a functional programming environment for prototyping in 3D, so I would like to have a haskell session which I can attach to this 3D environment. Any comments/feedback on the architecture/design of such a program would be appreciated. thanks ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Parsec float
Hi Everybody (especially Parsec Creator), is there any reason why float parses only positive numbers? I find following defition: float = lexeme floating ? float floating= do{ n - decimal ; fractExponent n } If floating was defined like floating= do{ n - integer ... or floating= do{ n - int ... instead then it would parse negative ones as well. Best regards, Bartek ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Parsec float
is there any reason why float parses only positive numbers? It is usual in parsing libraries to separate the recognition of a leading sign from recognition of the number itself: the sign-only parser can be reused in many contexts, e.g. in the Haskell'98 Numeric library, there is readSigned :: Real a = ReadS a - ReadS a which takes a secondary parser as its argument. You can instantiate that argument to any of readDec :: Num a = ReadS a readHex :: Num a = ReadS a readFloat :: Num a = ReadS a etc. I do not know if the equivalent of readSigned exists in Parsec, but it in polyparse's Text.Parse module, it is called parseSigned, rather unsurprisingly. Regards, Malcolm ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] ANNOUNCE: Hac φ: Haskell hackathon in Philadelphia, July 24-26
Greetings, I am very pleased to officially announce Hac phi, a Haskell hackathon/get-together to be held July 24-26 at the University of Pennsylvania in Philadelphia. The hackathon will officially kick off at 2:30 Friday afternoon, and go until 5pm on Sunday (with breaks for sleep, of course). Thanks to everyone who has already expressed interest in attending, it's shaping up to be a fun event. I want to stress that everyone is welcome---you do not have to be a Haskell guru to attend! Helping hack on someone else's project could be a great way to increase your Haskell-fu. If you plan on coming, please officially register [1], even if you already put your name on the wiki. Registration, travel, lodging and many other details can now be found on the Hac phi wiki [2]. We're also looking for a few people interested in giving short (15-20 min.) talks, probably on Saturday afternoon. Anything of interest to the Haskell community is fair game---a project you've been working on, a paper, a quick tutorial. If you'd like to give a talk, add it on the wiki [3]. Hope to see you in Philadelphia! -The Hac φ team [1] http://haskell.org/haskellwiki/Hac_%CF%86/Register [2] http://haskell.org/haskellwiki/Hac_%CF%86 [3] http://haskell.org/haskellwiki/Hac_%CF%86/Talks ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Error message reform (was: Strange type error with associated type synonyms)
Achim Schneider wrote: expected/encountered Expected/actual ? Familiar to users of test frameworks. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Who takes care of Haskell mailing lists?
Benjamin, I would like to create a mailing list for Portuguese speaking Haskell programmers. (...) According to Mailing lists - HaskellWiki (see http://haskell.org/haskellwiki/Mailing_lists), Thanks for your comprehensive reports. However, I did took all measures you sugested. Any problems with haskell or haskell-cafe should be reported to haskell-ad...@haskell.org, (...) OK. Sent also to haskell-admin. I misunderstood that address was only for problems, sorry for that. In addition, if you wish to suggest a new mailing list for Haskell, I would suggest first posting a message suggesting this idea (...) See this thread: http://www.haskell.org/pipermail/haskell-cafe/2009-May/061694.html It may help to notice that one of the mailing lists listed at the above-mentioned site is the following one for French readers: (...) You may wish to use the existence of this list as a basis for arguing that a Portuguese mailing list should be created. I think that is a good point. I said that in my message to the first address I found. My sugestion was to name the list 'haskell-pt', and the description could be Lista de discussão para os falantes da língua portuguesa (in Portuguese) or Mailing list for Portuguese speakers all over the world (in English, correct if necessary). Alternatively, there is the option of creating a Haskell-related mailing list outside of haskell.org, such as the following: I thought about that. But there are hundreds of millions of Portuguese speaking people, and probably a few thousands Haskell programmers, maybe 5 or 10 universities using it for undergraduate teaching, so I thought it would not be fair that I would be the list owner. I may not be doing Haskell in a few months, or die in a car accident, who knows? :) Best, Maurício ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Problem w/YAHT code example
This code, from YAHT (Section 8.4.2, PDF pg. 119 of 192) seems to have a problem. Code below. Michael = [mich...@localhost ~]$ ghci GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Prelude :l graph [1 of 1] Compiling Main ( graph.hs, interpreted ) graph.hs:6:24: lexical error at character '\8217' Failed, modules loaded: none. == Prelude data Graph v e = Graph [(Int,v)] [(Int,Int,e)] search :: Graph v e - Int - Int - Maybe [Int] search g@(Graph vl el) src dst | src == dst = Just [src] | otherwise = search’ el where search’ [] = Nothing search’ ((u,v,_):es) | src == u = case search g v dst of Just p - Just (u:p) Nothing - search’ es | otherwise = search’ es ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Problem w/YAHT code example
I'm not sure what you're using at the end of the identifier search', but it needs to be the single quote that's on the same key as the double quotes. I suspect that's where it's blowing up. On Thu, May 28, 2009 at 9:56 PM, michael rice nowg...@yahoo.com wrote: This code, from YAHT (Section 8.4.2, PDF pg. 119 of 192) seems to have a problem. Code below. Michael = [mich...@localhost ~]$ ghci GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Prelude :l graph [1 of 1] Compiling Main ( graph.hs, interpreted ) graph.hs:6:24: lexical error at character '\8217' Failed, modules loaded: none. == Prelude data Graph v e = Graph [(Int,v)] [(Int,Int,e)] search :: Graph v e - Int - Int - Maybe [Int] search g@(Graph vl el) src dst | src == dst = Just [src] | otherwise = search’ el where search’ [] = Nothing search’ ((u,v,_):es) | src == u = case search g v dst of Just p - Just (u:p) Nothing - search’ es | otherwise = search’ es ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Data.Binary and little endian encoding
On Thu, May 28, 2009 at 11:39 AM, John Van Enk vane...@gmail.com wrote: Writing instances encode/decode that use either little endian or big endian (or mixed!) is trivial... see attached file. I don't see where your problem is... Inexperience, lack of enough contiguous time to digest everything at once (till now), thank you for your most detailed example! This should be wiki'd. Dave On Thu, May 28, 2009 at 12:35 PM, David Leimbach leim...@gmail.comwrote: On Thu, May 28, 2009 at 9:17 AM, John Van Enk vane...@gmail.comwrote: Fair enough. I am just new to the interface, wondering if I should try matching responses by pulling apart via Get, or the bit syntax package. I'm assming you have some 'data Foo = ...'? If this is the case, you're probably okay writing an instance of Binary for Foo and using encode/decode. That's all I've had to do and had superb performance. encode/decode do Big Endian, and 9P does little endian. From the man page: Each message consists of a sequence of bytes. Two–, four–, and eight–byte fields hold unsigned integers represented in little–endian order (least significant byte first). encode/decode just won't work for me as a result, as they assume the not-so-aptly-named (at least in this case) network byte order. Since I'm not Rob Pike, or Ken Thompson or any of the Plan 9 guys, I can't tell you why they chose little endian for this. (I should note that I sometimes work with CAN hardware, and depending on what people want to put on the line, little endian creeps in there too, so this issue will have to be dealt with here as well, if I am to use Data.Binary) I've got (typing from memory, forgive syntax errors) module Nine (Message) where {-- missing imports --} notag = putWord16le -1 -- Message type field values -- from: http://plan9.bell-labs.com/sources/plan9/sys/include/fcall.h tversion = 100 rversion = 101 rerror = 107 -- only 9P2000 is being handled so some constructors are simple data Message = Tversion | Rversion {size :: Int, tag :: Int, msize :: Int, version :: String} | Rerror {message :: String} -- maybe this should be Maybe ByteString? ... instance Binary Message where put Tversion = putWord32le 16 tversion notag msize 9P2000 put Rversion = putWord32le 16 rversion notag msize 9P2000 get = do size - getWord32le tag - getWord8 case tag of rversion - do msize - getWord32le version - getRemainingLazyByteString return (Rversion size tag msize (C.unpack version)) === I'm beginning to feel the Get Monad is not going to be as nice as if I had some bit-syntax for determining what type of return message I'm getting. Any T message can be met with the paired R response, or an Rerror message, with a detailed description of what went wrong. My instance of get is looking like it's going to be pretty nasty :-) The first message in any 9p session is Tversion with Rversion or Rerror response. There's optional authentication hooks via Tauth/Rauth, and then the filesystem namespace navigation operation messages. Dave /jve ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- /jve ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What's the problem with iota's type signature?
michael rice wrote: Yeah, I went back and tried double again, though I'd swear I got the dang thing to compile (and run) w/o errors. I guess I meant Num. So Num is a class and Int and Integer are types? What are the other classes? Docs? Unification, for me, is pattern matching ala Prolog. What's the meaning in Haskell? Docs? I've been digging into this stuff for months and it's still tripping me up. Very frustrating. As others have mentioned, using GHCi can give you a lot of information. GHCi commands begin with a colon followed by the command (kinda like vi), whereas anything not beginning with a colon is treated as a Haskell expression to be evaluated. The :? command will list all the GHCi commands, which is a good place to start. The :type command takes a Haskell expression and prints the type inferred for it. You can also use the command :set +t which will make GHCi print the type after evaluating each expression; you may want to use this until you get the hang of things. The :info command takes a whitespace separated list of identifiers and will print their type and other information (e.g. what module it comes from, what type class a function belongs to, all the functions that are members of a type class, fixity of operators,...) As far as type classes and the like, there are a bunch. Hoogle[1] is an excellent API search engine for looking up this kind of stuff. Just enter the name of a function, type class, data type, or enter a type signature. The results give links to the online Haddock documentation (either GHC official docs, or Hackage docs). Unification is used when doing type inference. It's the same unification as in Prolog, only at the type level. Because of the way inference works, it happens that the |a| and |b| type variables must be unified for both of the functions you gave. A whole lot more can be said here, though I'm not sure how much you care :) The Wikipedia page on Hindley--Milner[2] gives a good starting point, though Haskell's type inference has more bells and whistles than the basic HM algorithm. [1] http://haskell.org/hoogle/ [2] http://en.wikipedia.org/wiki/Hindley-Milner -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: We tried this functional, higher-order stuff with LISP and look what happened...
2009/05/28 Benjamin L.Russell dekudekup...@yahoo.com: What makes you think that Haskell is likely eventually to dig a smoking hole in the ground? This is more about unmet expectations than spectacular failure. -- Jason Dusek ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Error message reform
Claus Reinke wrote: Still, I would really like a just the facts, please mode for GHC, with less text and more type signatures (especially for the contexts of type mismatches). Error messages simply not including the information I need has become my main issue with GHC messages, and seems to be a common thread over many tickets and threads apparently discussing phrasing (eg, expected/inferred: who expects and why, and what is the inference based on?). FWIW, the suggestion I floated has less text than the current message while preserving all the type and expression information ;) (Though it doesn't necessarily generalize to cover similar messages like: Prelude :t (\x - x) :: a - b interactive:1:7: Couldn't match expected type `b' against inferred type `a' `b' is a rigid type variable bound by the polymorphic type `forall a b. a - b' at interactive:1:0 `a' is a rigid type variable bound by the polymorphic type `forall a b. a - b' at interactive:1:0 In the expression: x ) Just, please, keep in mind that there is no one-size-fits-all: improving a message for one group of users might well make it less useful for another group. +1. There're worlds of difference between the kinds of error messages suitable for beginners, vs regular users, vs type-level programmers. Also, while a user may have some given level of understanding, the level of messaging they'll want can vary a lot depending on the task a hand. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Problem w/YAHT code example
Thanks! I just copied the code from the PDF file. Whatever that character was it wasn't the correct one. Michael --- On Thu, 5/28/09, Andrew Wagner wagner.and...@gmail.com wrote: From: Andrew Wagner wagner.and...@gmail.com Subject: Re: [Haskell-cafe] Problem w/YAHT code example To: michael rice nowg...@yahoo.com Cc: haskell-cafe@haskell.org Date: Thursday, May 28, 2009, 10:01 PM I'm not sure what you're using at the end of the identifier search', but it needs to be the single quote that's on the same key as the double quotes. I suspect that's where it's blowing up. On Thu, May 28, 2009 at 9:56 PM, michael rice nowg...@yahoo.com wrote: This code, from YAHT (Section 8.4.2, PDF pg. 119 of 192) seems to have a problem. Code below. Michael = [mich...@localhost ~]$ ghci GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Prelude :l graph [1 of 1] Compiling Main ( graph.hs, interpreted ) graph.hs:6:24: lexical error at character '\8217' Failed, modules loaded: none. == Prelude data Graph v e = Graph [(Int,v)] [(Int,Int,e)] search :: Graph v e - Int - Int - Maybe [Int] search g@(Graph vl el) src dst | src == dst = Just [src] | otherwise = search’ el where search’ [] = Nothing search’ ((u,v,_):es) | src == u = case search g v dst of Just p - Just (u:p) Nothing - search’ es | otherwise = search’ es ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] What's the problem with iota's type signature?
And I thought everyone was puzzling these type signatures out all by themselves. ;-) The Haskell learning curve is about the steepest I've ever seen for a computer language, but I think I'm catching on. Thanks for the info. Michael --- On Thu, 5/28/09, wren ng thornton w...@freegeek.org wrote: From: wren ng thornton w...@freegeek.org Subject: Re: [Haskell-cafe] What's the problem with iota's type signature? To: Haskell-cafe haskell-cafe@haskell.org Date: Thursday, May 28, 2009, 11:14 PM michael rice wrote: Yeah, I went back and tried double again, though I'd swear I got the dang thing to compile (and run) w/o errors. I guess I meant Num. So Num is a class and Int and Integer are types? What are the other classes? Docs? Unification, for me, is pattern matching ala Prolog. What's the meaning in Haskell? Docs? I've been digging into this stuff for months and it's still tripping me up. Very frustrating. As others have mentioned, using GHCi can give you a lot of information. GHCi commands begin with a colon followed by the command (kinda like vi), whereas anything not beginning with a colon is treated as a Haskell expression to be evaluated. The :? command will list all the GHCi commands, which is a good place to start. The :type command takes a Haskell expression and prints the type inferred for it. You can also use the command :set +t which will make GHCi print the type after evaluating each expression; you may want to use this until you get the hang of things. The :info command takes a whitespace separated list of identifiers and will print their type and other information (e.g. what module it comes from, what type class a function belongs to, all the functions that are members of a type class, fixity of operators,...) As far as type classes and the like, there are a bunch. Hoogle[1] is an excellent API search engine for looking up this kind of stuff. Just enter the name of a function, type class, data type, or enter a type signature. The results give links to the online Haddock documentation (either GHC official docs, or Hackage docs). Unification is used when doing type inference. It's the same unification as in Prolog, only at the type level. Because of the way inference works, it happens that the |a| and |b| type variables must be unified for both of the functions you gave. A whole lot more can be said here, though I'm not sure how much you care :) The Wikipedia page on Hindley--Milner[2] gives a good starting point, though Haskell's type inference has more bells and whistles than the basic HM algorithm. [1] http://haskell.org/hoogle/ [2] http://en.wikipedia.org/wiki/Hindley-Milner -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe