Re: [Haskell-cafe] Best way to build a GHC backend?
2012/7/8 Jonathan Geddes geddes.jonat...@gmail.com: Venerable Haskell Hackers, I love Haskell and think it should run everywhere. Now supposing I would like to build another backend for GHC, perhaps for Java Bytecode, .Net CIL, or JavaScript, What would be the best way to approach that? I can think of a few options: 1. Produce External Core with -fext-core and compile that with a completely separate compiler 2. Use the GHC apis to build a compiler that reuses a load of GHC's code, but has it's own backend 3. Add a new backend directly into GHC Any other options? You can target LLVM bitcode and transform that. And there probably is an LLVM backend for your favourite target already. While I'm on the subject, why has Haskell not been ported to the likes of the JVM, .NET CLR, or JavaScript? Are Haskell's non-strict semantics just too different from the semantics of these other platforms? http://www.haskell.org/haskellwiki/GHC/FAQ#Why_isn.27t_GHC_available_for_.NET_or_on_the_JVM.3F It would make a lot of sense to give GHC a .NET or JVM back end, and it's a question that comes up regularly. The reason that we haven't done it here, at GHC HQ, is because it's a more substantial undertaking than might at first appear (see below). Furthermore, it'd permanently add a complete new back-end platform for us to maintain. Given our rather limited development effort, we have so far not bitten the bullet, and we have no immediate plans to do so. The big problem seems to be to create a sensible interop to an object-orientated framework. SPJ is known for saying that Haskell's plan for world domination is support for many parallelism/concurrency idioms. I believe running on many platforms is just as important. From my point of view, languages that cannot run on one of the 3 aforementioned platforms will become irrelevant. (with the exception of C, of course). Thoughts? Javascript (or a possiible common browser VM) seems essential. Server-side nobody knows or cares what you run on. It would be nice to be able to interop with Java or dotnet though. --J Arthur ___ 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] vector-simd: some code available, and some questions
On Sun, Jul 8, 2012 at 3:05 AM, Nicolas Trangez nico...@incubaid.com wrote: On Sun, 2012-07-08 at 01:40 +0200, Gábor Lehel wrote: unsafeXorSSE42 :: (Storable a, SV.AlignedToAtLeast SV.A16 o1, SV.Alignment o1, SV.AlignedToAtLeast SV.A16 o2, SV.Alignment o2, SV.AlignedToAtLeast SV.A16 o3, SV.Alignment o3) = SV.Vector o1 a - SV.Vector o2 a - SV.Vector o3 a I wonder if you could get that a bit shorter... I suppose you could write: instance (AlignedToAtLeast n a, AlignedToAtLeast n b) = AlignedToAtLeast n (a, b) instance (AlignedToAtLeast n a, AlignedToAtLeast n b, AlignedToAtLeast n c) = AlignedToAtLeast n (a, b, c) ...and so on... Once again, nifty! And implemented in [1]. though it feels a little strange semantically (relating a tuple to a scalar), but I don't see what harm can come of it. And then you can just write SV.AlignedToAtLeast SV.A16 (o1, o2, o3) in signatures. You can also make (Alignment n, Alignment a) a superclass constraint of AlignedToAtLeast, and write instances for Alignment inductively on One and Twice, and then you don't have to write Alignment o1 etc. separately either. So the signature would be just: unsafeXorSSE42 :: (Storable a, SV.AlignedToAtLeast SV.A16 (o1, o2, o3)) = SV.Vector o1 a - SV.Vector o2 a - SV.Vector o3 a which is friendlier. I implemented the inductive alignment calculation over One and Twice (good idea, and easy to do), but I don't get the thing about superclasses. I've been trying several approaches (including definitions based on forall and other trickery I never used before), but didn't get things to work, at least: the compiler always said I'd need UndecidableInstances, and that sounds scary... Care to elaborate? All I meant was class (Alignment n, Alignment a) = AlignedToAtLeast n a but I got a bit ahead of myself, because that rules out the instance on tuples. (I suppose you *could* write some kind of Alignment instance for them, taking their minimum or something, but that's getting a bit too subversive for me). The alternative, if you want both Alignment as a superclass and the ability to constrain multiple types at once, is to have the above, remove the instance on tuples, and instead something like: class (AlignedToAtLeast n a, AlignedToAtLeast n b) = AlignedToAtLeast2 n a b instance (AlignedToAtLeast n a, AlignedToAtLeast n b) = AlignedToAtLeast2 n a b class (AlignedToAtLeast n a, AlignedToAtLeast n b, AlignedToAtLeast n c) = AlignedToAtLeast3 n a b c instance (AlignedToAtLeast n a, AlignedToAtLeast n b, AlignedToAtLeast n c) = AlignedToAtLeast3 n a b c (feel free to think of better names!) unsafeXorSSE42 :: (Storable a, SV.AlignedToAtLeast3 SV.A16 o1 o2 o3) = SV.Vector o1 a - SV.Vector o2 a - SV.Vector o3 a That will require UndecidableInstances, but all that means is that GHC can't prove to itself that instance checking will terminate. So you could end up getting the compiler into an infinite loop (or in practice, to exceed its recursion limit). But it doesn't allow anything unsafe to happen at runtime, and there's plenty of perfectly good instances which terminate even if GHC can't prove it. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Which mailing list for GHC hacking discussion?
Hi all, For GHC development questions (ie hacking on GHC, not with GHC) which is the appropriate mailing list ghc-cvs or ghc-users? Cheers, Erik -- -- Erik de Castro Lopo http://www.mega-nerd.com/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Best way to build a GHC backend?
* Niklas Larsson: http://www.haskell.org/haskellwiki/GHC/FAQ#Why_isn.27t_GHC_available_for_.NET_or_on_the_JVM.3F It would make a lot of sense to give GHC a .NET or JVM back end, and it's a question that comes up regularly. The reason that we haven't done it here, at GHC HQ, is because it's a more substantial undertaking than might at first appear (see below). Furthermore, it'd permanently add a complete new back-end platform for us to maintain. Given our rather limited development effort, we have so far not bitten the bullet, and we have no immediate plans to do so. The big problem seems to be to create a sensible interop to an object-orientated framework. I think this is completely backwards. The hard part is porting the STG machine to the JVM in such a way that performance (speed and memory consumption) is acceptable. A toy port is probably not that hard if you know you way around in GHC, but its performance will be horrible. Useful Java interop is easy once you run on the JVM. There are already bindings for large OO code bases with their own object systems, so it's definitely possible to access OO code. Seemless interop is very difficult, but I don't think it's necessary. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] vector-simd: some code available, and some questions
I've not been following this thread very closely, but it seems like what you're trying to do may be related to Geoffrey Mainland's work on SIMD support in GHC. See [1] for his SIMD-enabled version of the vector library. He's also written some blog posts about this [2]. Reiner [1] https://github.com/mainland/vector [2] http://ghc-simd.blogspot.com.au/ On 8 July 2012 05:13, Nicolas Trangez nico...@incubaid.com wrote: All, After my message of yesterday [1] I got down to it and implemented something along those lines. I created a playground repository containing the code at [2]. Initial benchmark results at [3]. More about the benchmark at the end of this email. First some questions and requests for help: - I'm stuck with a typing issue related to 'sizeOf' calculation at [4]. I tried a couple of things, but wasn't able to figure out how to fix it. - I'm using unsafePerformIO at [5], yet I'm not certain it's OK to do so. Are there better (safer/performant/...) ways to get this working? - Currently Alignment phantom types (e.g. A8 and A16) are not related to each other: a function (like Data.Vector.SIMD.Algorithms.unsafeXorSSE42) can have this signature: unsafeXorSSE42 :: Storable a = SV.Vector SV.A16 a - SV.Vector SV.A16 a - SV.Vector SV.A16 a Yet, imaging I'd have an SV.Vector SV.A32 Word8 vector at hand, the function should accept it as well (a 32-byte aligned vector is also 16-byte aligned). Is there any way to encode this at the type level? That's about it :-) As of now, I only implemented a couple of the vector API functions (the ones required to execute my benchmark). Adding the others should be trivial. The benchmark works with Data.Vector.{Unboxed|Storable}.Vector (UV and SV) vectors of Word8 values, as well as my custom Data.Vector.SIMD.Vector type (MV) using 16-byte alignment (MV.Vector MV.A16 Word8). benchUV, benchSV and benchMV all take 2 pre-calculated Word8 vectors of given size (1024 and 4096) and xor them pairwise into the result using zipWith xor. benchMVA takes 2 suitable MV vectors and xor's them into a third using a rather simple and unoptimized C implementation using SSE4.2 intrinsics [6]. This could be enhanced quite a bit (I guess using the prim calling convention, FFI overhead can be reduced as well). Currently, only vectors of a multiple of 32 bytes are supported (mostly because of laziness on my part). As you can see, the zipWith Data.Vector.SIMD implementation is slightly slower than the Data.Vector.Storable based one. I didn't perform much profiling yet, but I suspect allocation and ForeignPtr creation is to blame, this seems to be highly optimized in GHC.ForeignPtr.mallocPlainForeignPtrBytes as used by Data.Vector.Storable. Thanks for any input, Nicolas [1] http://www.haskell.org/pipermail/haskell-cafe/2012-July/102167.html [2] https://github.com/NicolasT/vector-simd/ [3] http://linode2.nicolast.be/files/vector-simd-xor1.html [4] https://github.com/NicolasT/vector-simd/blob/master/src/Data/Vector/SIMD/Algorithms.hs#L46 [5] https://github.com/NicolasT/vector-simd/blob/master/src/Data/Vector/SIMD/Algorithms.hs#L43 [6] https://github.com/NicolasT/vector-simd/blob/master/cbits/vector-simd.c#L47 ___ 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] Connecting Travis CI and hackage
*tldr*: is there a way to upload package to hackage from Travis automatically and safely (hiding password to hackage account)? Several days ago I discovered Travis ( http://travis-ci.org/ ) - nice open source build-service, easy to start and monitoring. I've configured some github projects and add build status to it's readme. It's usable to know how is your haskell package building on separate fresh machine. Following git-flow developing model there is a develop branch for snapshots and master branch for release. That why every commit in master branch should produce new release build ⇒ every commit in master branch should produce new hackage build upload. And also it will be nice to have that routine process done automatically. It could be done using cabal-upload tool and --username and --password options. But it means that .travis.yml file should contain my hackage-password explicitly. How can I avoid that? -- Best regards, dmitry malikov ! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] vector-simd: some code available, and some questions
On Sun, 2012-07-08 at 20:49 +1000, Reiner Pope wrote: I've not been following this thread very closely, but it seems like what you're trying to do may be related to Geoffrey Mainland's work on SIMD support in GHC. See [1] for his SIMD-enabled version of the vector library. He's also written some blog posts about this [2]. Thanks. I knew about this before (did at least some research ;-)), yet I think the scope is somewhat different (assuming my playground work has any scope at all...). I think Geoffreys work goes much further than what I'm trying to accomplish: it's not my intention to write SIMD-based code at a high level (which is, obviously, a great thing, but beyond my capabilities as of now I'm afraid). What I'd like to achieve is to be able to write SIMD code at the C level (or have SIMD code generated somehow through LLVM/Clang(/Poly?), ISPC or others), and call into this from Haskell, providing some guarantees w.r.t. alignment (and maybe length-in-bytes as well?) of the passed vector pointers (which you don't get when using plain Storable vectors as far as I could find/see). Consider it a very short-term stop-gap solution until the tools are in place to write high-level code which yields the same performance as a more low-level (assembly-level) implementation. Nicolas ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] vector-simd: some code available, and some questions
On Sun, 2012-07-08 at 10:27 +0200, Gábor Lehel wrote: On Sun, Jul 8, 2012 at 3:05 AM, Nicolas Trangez nico...@incubaid.com wrote: I implemented the inductive alignment calculation over One and Twice (good idea, and easy to do), but I don't get the thing about superclasses. I've been trying several approaches (including definitions based on forall and other trickery I never used before), but didn't get things to work, at least: the compiler always said I'd need UndecidableInstances, and that sounds scary... Care to elaborate? All I meant was class (Alignment n, Alignment a) = AlignedToAtLeast n a but I got a bit ahead of myself, because that rules out the instance on tuples. Maybe that's one of the things I ran into, can't remember OTOH. (I suppose you *could* write some kind of Alignment instance for them, taking their minimum or something, but that's getting a bit too subversive for me). Heh, it already feels evil-but-in-a-good-and-powerful-way to me right now ;-) Thanks for all your input! The alternative, if you want both Alignment as a superclass and the ability to constrain multiple types at once, is to have the above, remove the instance on tuples, and instead something like: class (AlignedToAtLeast n a, AlignedToAtLeast n b) = AlignedToAtLeast2 n a b instance (AlignedToAtLeast n a, AlignedToAtLeast n b) = AlignedToAtLeast2 n a b class (AlignedToAtLeast n a, AlignedToAtLeast n b, AlignedToAtLeast n c) = AlignedToAtLeast3 n a b c instance (AlignedToAtLeast n a, AlignedToAtLeast n b, AlignedToAtLeast n c) = AlignedToAtLeast3 n a b c (feel free to think of better names!) unsafeXorSSE42 :: (Storable a, SV.AlignedToAtLeast3 SV.A16 o1 o2 o3) = SV.Vector o1 a - SV.Vector o2 a - SV.Vector o3 a Implemented in [1]. Code says unsafeXorSSE42 :: (Storable a, SV.AlignedToAtLeast3 SV.A16 o1 o2 o3) = SV.Vector o1 a - SV.Vector o2 a - SV.Vector o3 a ghci says unsafeXorSSE42 :: (AlignedToAtLeast (Data.Vector.SIMD.Mutable.Twice A8) o2, AlignedToAtLeast (Data.Vector.SIMD.Mutable.Twice A8) o1, AlignedToAtLeast (Data.Vector.SIMD.Mutable.Twice A8) o3, Foreign.Storable.Storable a) = Vector o1 a - Vector o2 a - Vector o3 a which is the same thing, so should do. That will require UndecidableInstances, but all that means is that GHC can't prove to itself that instance checking will terminate. So you could end up getting the compiler into an infinite loop (or in practice, to exceed its recursion limit). But it doesn't allow anything unsafe to happen at runtime, and there's plenty of perfectly good instances which terminate even if GHC can't prove it. I see. I had some rather unsafe/undecidable-by-a-developer things in mind, but I guess I should read up on some of the language extensions GHC provides. Thanks, Nicolas [1] https://github.com/NicolasT/vector-simd/commit/8f934891c9630a96ce009fafa7f6ba70df306d4f ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Best way to build a GHC backend?
I agree that the Raison d'être for a .NET or JVM backend is interop. Perhaps that's not worth the effort of an entirely new backend. JavaScript is a different beast, however. I said before: From my point of view, languages that cannot run on one of the 3 aforementioned platforms will become irrelevant. (with the exception of C, of course). I'll take that one step further and say that for web applications it is becoming increasingly difficult to justify using a language that WILL NOT run both client and server. JavaScript (with NodeJS), Clojure (with ClojureScript), and Dart are just a few examples. I really believe that with a solid JavaScript backend, Haskell would be an ideal web application language. Am I alone in that belief? What can I do to get the ball rolling on that? --J Arthur ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Control defaulting in ghci
Is there a way to control defaulting in ghci? (Like the default declaration in source files does.) ghci 7.4.1 doesn't accept default declarations. I tried loading a module with a default declaration, but that also didn't affect the ghci session. It would be ironic if this is possible in source files but not in ghci, since defaulting is much more useful in an interactive session than in modules. -- Roman I. Cheplyaka :: http://ro-che.info/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Connecting Travis CI and hackage
There is a broader plan, about having Hackage2 (in development) and scoutess (same) work together, but we're not there yet *at all*. But in the meantime, regarding what you suggest here, couldn't be done through tags rather than branches? Tagging a release version could trigger testing and, if testing runs fine, upload to hackage. On Sun, Jul 8, 2012 at 1:21 PM, Dmitry Malikov malikov@gmail.comwrote: *tldr*: is there a way to upload package to hackage from Travis automatically and safely (hiding password to hackage account)? Several days ago I discovered Travis ( http://travis-ci.org/ ) - nice open source build-service, easy to start and monitoring. I've configured some github projects and add build status to it's readme. It's usable to know how is your haskell package building on separate fresh machine. Following git-flow developing model there is a develop branch for snapshots and master branch for release. That why every commit in master branch should produce new release build ⇒ every commit in master branch should produce new hackage build upload. And also it will be nice to have that routine process done automatically. It could be done using cabal-upload tool and --username and --password options. But it means that .travis.yml file should contain my hackage-password explicitly. How can I avoid that? -- Best regards, dmitry malikov ! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Alp Mestanogullari ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Connecting Travis CI and hackage
But in the meantime, regarding what you suggest here, couldn't be done through tags rather than branches? Tagging a release version could trigger testing and, if testing runs fine, upload to hackage. Testing should be done on travis virtual machine. So this question is not about `when' or `where from' new release should be generated. It's about how uploading the new package to hackage could be done from the travis machine. -- Best regards, dmitry malikov ! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Control defaulting in ghci
On 7/8/2012 11:28 AM, Roman Cheplyaka wrote: Is there a way to control defaulting in ghci? (Like the default declaration in source files does.) ghci 7.4.1 doesn't accept default declarations. I tried loading a module with a default declaration, but that also didn't affect the ghci session. It would be ironic if this is possible in source files but not in ghci, since defaulting is much more useful in an interactive session than in modules. I've too wanted this for quite some time, so I have created a ticket + a patch[1] that implements this feature. Feel free to test it. [1]: http://hackage.haskell.org/trac/ghc/ticket/7061 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Haskell User Group Hamburg (Germany) - Meeting Thursday July 12th 2012
Hello cafe, there's an upcomming meeting of the Haskell user group Hamburg next Thursday (July 12th). We'll start 19:00 at the Xing AG in Hamburg (Dammtorstraße 35, 20354 Hamburg ). Jan Ahrens will give a short talk about web development with Yesod ( http://www.yesodweb.com/). Although this announcement is written in english the talk will be given in german. If you are interested to join us, have a look at our doodle (also in german) http://www.doodle.com/5ekivcacuam9czxs Further announcements will be made via Twitter, so you may want to follow https://twitter.com/hug_hh. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Interest in typed relational algebra library?
Yes, that would be very nice! Type-checked queries really is a must, but I´ve found HaskellDB too cumbersome to work with. -Rune On Sat, Jul 7, 2012 at 11:45 AM, Paul Visschers m...@paulvisschers.net wrote: Hello, I've been out of the Haskell game for a bit, but now I'm back. A couple of years ago I made a small library that implements relational algebra with types so that malformed queries and other operations are caught at compile time. It is heavily based off of the internals of HaskellDB (see http://hackage.haskell.org/packages/archive/haskelldb/2.1.1/doc/html/Database-HaskellDB-PrimQuery.html), but types so that it can actually be used directly instead of having to use HaskellDB's query monad. Besides the joy of using relational algebra directly in your code, this also means that you can make query-optimizing code in a type-safe way, you can subquery results returned by the database directly without accessing the database again and you have more options when converting from relation algebra to SQL or another query language. The library isn't quite ready for release, but I might want to work on it a bit and then release it. Is anyone interested in such a library? Paul Visschers ___ 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] Interest in typed relational algebra library?
Is this anything like the hssqlppp package? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] DPH matrix product
Hi, I'm trying to implement a matrix product example using DPH. This is the code: --- type MMultType = Double type Matrix = [:[:MMultType:]:] type MVector = [:MMultType:] type Matrix_wrapper = PArray (PArray MMultType) {-# NOINLINE matMult_wrapper #-} matMult_wrapper :: Matrix_wrapper - Matrix_wrapper - Matrix_wrapper matMult_wrapper mA mB = toPArrayP (mapP toPArrayP (matMult (fromNestedPArrayP mA) (fromNestedPArrayP mB))) matMult :: Matrix - Matrix - Matrix matMult mA mB = mapP (\row - mapP (\col - dotp row col) (transposeP mB)) mA dotp :: MVector - MVector - MMultType dotp row col = D.sumP (zipWithP (D.*) row col) transposeP :: Matrix - Matrix transposeP m = let h = lengthP m w = lengthP (m !: 0) rh = I.enumFromToP 0 (h I.- 1) rw = I.enumFromToP 0 (w I.- 1) in if h I.== 0 then [: :] else mapP (\y - mapP (\x - m !: x !: y) rh) rw --- My problem is at execution time, on matrices of size 300*300 the program does finish (although it is very slow), but on 700*700 it consumes GBs of RAM until the process is aborted. In the paper Work Efficient Higher-Order Vectorisation it is explained that a work complexity problem (wich involved unnecesary array replication) was recently treated. So at first I thought the code implementation related to the paper had not been uploaded to hackage. But as I understand it must have been, as that seems to be the motive of the dph-lifted-vseg package. Does anybody notice the problem with the example or if the problem is related to the subject treated in the paper? Thanks in advance! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] ANNOUNCE: control-monad-loop 0.1
This package provides imperative-style loops supporting continue and break. For example: import Control.Monad import Control.Monad.IO.Class import Control.Monad.Trans.Loop import Control.Monad.Trans.Class main :: IO () main = foreach [0..] $ \i - foreach [0..] $ \j - do when (j == 0) $ continue-- skip to next iteration when (j = 5) $ exit-- exit the loop when (i = 5) $ lift exit -- exit the outer loop by calling 'exit' in the parent monad liftIO $ print (i, j) It works by having the loop body run under the LoopT monad transformer, which provides early exit functions 'continue' and 'exit'. Functions like 'foreach' and 'while' run a LoopT callback, passing it continuations defining 'continue' and 'exit'. http://hackage.haskell.org/package/control-monad-loop ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe