RE: FixIO/ Tackling Awkward Squad
| Dear Haskellers, | After enjoying "Tackling the Awkward Squad" (Simon | Peyton Jones), I wonder what other elements of the | squad can be tackled in a simular way? Right now I am | thinking about FixIO. This little bugger seems to show | up in a lot of code! Can we give it an operational | semantics a la Tackling the awkward squad? I am quite | stumped on this one, so i wont event post my meager | attempts, but rather hope someone brighter then me | will :) We need to add a new Value "FixIO N"... I'd be inclined to do it like this: fixIO m = do { v <- newEmptyMVar ; result <- m (unsafePerformIO (takeMVar v)) ; putMVar v result ; return result } Of course, this just begs the question of what exactly unsafePerformIO might mean, and we can only really answer that when we give an operational semantics to the functional part of the language as well as the imperative part. But perhaps the meaning of fixIO becomes clearer with the above. (Of course an implementation is free to implement it some other way too.) Simon
--- Simon Peyton-Jones <simonpj@microsoft.com> wrote:
fixIO m = do { v <- newEmptyMVar ; result <- m (unsafePerformIO (takeMVar v)) ; putMVar v result ; return result }
Of course, this just begs the question of what exactly unsafePerformIO might mean, and we can only really answer that when we give an operational semantics to the functional part of the language as well as the imperative part.
Ok, I do see how fixIO works.. thanks! I see what you mean about needing an operational semantics for the functional part too. Actually I was hoping to use fixIO to help explain unsafeInterleaveIO, but I fixIO dont work that way:). I can easily do unsafeInterleaveIO in terms of unsafePerformIO, so perhaps that leaves me in the quandry of needed operational semantics for the whole language, so perhaps I better give up on that sticky bit, for the moment. This all started when I was trying to understand what was going on in the SOE implementation of Fran. They use getChannelContents (?) which just does more magic that I could deal with. Maybe I will go back to plan B: try to implement fran like system without lazy event lists, since I cant think of anyway to construct them without magic :) Cheers! __________________________________________________ Do You Yahoo!? Get personalized email addresses from Yahoo! Mail - only $35 a year! http://personal.mail.yahoo.com/
Fri, 16 Feb 2001 04:14:26 -0800, Simon Peyton-Jones <simonpj@microsoft.com> pisze:
fixIO m = do { v <- newEmptyMVar ; result <- m (unsafePerformIO (takeMVar v)) ; putMVar v result ; return result }
If we have unsafePerformIO, why not this? fixIO m = let x = unsafePerformIO (m x) in return $! x -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK
Marcin 'Qrczak' Kowalczyk wrote:
Fri, 16 Feb 2001 04:14:26 -0800, Simon Peyton-Jones <simonpj@microsoft.com> pisze:
fixIO m = do { v <- newEmptyMVar ; result <- m (unsafePerformIO (takeMVar v)) ; putMVar v result ; return result }
If we have unsafePerformIO, why not this?
fixIO m = let x = unsafePerformIO (m x) in return $! x
Why the strict application? You probably want: do { fixIO (\x -> return (x+1)); return 2 } to evaluate to (return 2). But the version with strict application diverges. By the way, we can prove that it should evaluate to (return 2) using the monadic-fixpoint axiomatization: do { fixIO (\x -> return (x+1)); return 2 } = {expand do} fixIO (\x -> return (x+1)) >>= \_ -> return 2 = {rewrite} fixIO (return . (+1)) >>= \_ -> return 2 = {mfix (return . h) = return (fix h), mfix = fixIO for the IO monad} return (fix (+1)) >>= \_ -> return 2 = {return x >>= f = f x} return 2 So, it looks like: fixIO m = let x = unsafePerformIO (m x) in return x will do a better job. -Levent.
I recently wrote:
So, it looks like:
fixIO m = let x = unsafePerformIO (m x) in return x
will do a better job.
But of course, I forgot to make my point before sending the message! The non-strict version is not good either, because it won't do the effects! Consider the definition: fixIO m = let x = unsafePerformIO (m x) in return x and the expression: do { fixIO (\x -> do {putStr "hello"; return (x+1)}); return 2 } We want this to first print hello and then return 2. The non-strict version will return the 2, but will not print the "hello". And the strict version will print the "hello" but won't return the 2. We want both. Hence neither definition is sufficient. -Levent.
Fri, 16 Feb 2001 10:01:06 -0800, Levent Erkok <erkok@cse.ogi.edu> pisze:
The non-strict version is not good either, because it won't do the effects!
data Box a = Box {unbox :: a} fixIO m = let x = unsafePerformIO (liftM Box (m (unbox x))) in return (unbox $! x) -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK
Marcin 'Qrczak' Kowalczyk wrote:
Fri, 16 Feb 2001 10:01:06 -0800, Levent Erkok <erkok@cse.ogi.edu> pisze:
The non-strict version is not good either, because it won't do the effects!
data Box a = Box {unbox :: a}
fixIO m = let x = unsafePerformIO (liftM Box (m (unbox x))) in return (unbox $! x)
But that doesn't do the effects either.. I tried: data Box a = Box {unbox :: a} fixIOMQ :: (a -> IO a) -> IO a fixIOMQ m = let x = unsafePerformIO (liftM Box (m (unbox x))) in return (unbox $! x) and: do { x <- fixIOMQ (\x -> do {putStr "hello"; return (x+1)}); return 2} Which did NOT print hello on the screen, before returning 2. Maybe I'm missing your point? By the way, the original version that Simon PJ wrote (with mvar's) didn't have any of these problems. -Levent.
Fri, 16 Feb 2001 10:49:14 -0800, Levent Erkok <erkok@cse.ogi.edu> pisze:
fixIO m = let x = unsafePerformIO (liftM Box (m (unbox x))) in return (unbox $! x)
But that doesn't do the effects either..
Sorry, this one should be OK: fixIO m = let x = unsafePerformIO (liftM Box (m (unbox x))) in return . unbox $! x
By the way, the original version that Simon PJ wrote (with mvar's) didn't have any of these problems.
But used a heavy concept of concurrency to express something which is more fundamental and doesn't need concurrency. -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK
Sorry, this one should be OK:
fixIO m = let x = unsafePerformIO (liftM Box (m (unbox x))) in return . unbox $! x
Unfortunately, that's not good either: Consider again: e :: IO Int e = do { x <- fixIO (\x -> do {putStr "hello"; return (x+1)}); return 2} If I run e several times, I should see "hello" each time on my screen. But that doesn't happen with this definition: Main> e hello2 Main> e 2 Main> e 2 I see the effect only the first time I run it. But e has type IO Int, hence each time I run it, I should see the string hello. If I use the library version of fixIO (found in IOExts) or Simon PJ's version, hello is printed each time e is run, which is the correct behavior. -Levent.
Does anyone know of a tutorial introduction to the FFI? How does one go about getting started with this thing? Any simple examples? I just want to be able to do simple things (mostly access a c library from haskell... ok maybe not trivial :) ) I would be happy if I could just call c programs with simple types and pointers (no way am I going to figure out struct alignment! ). I have had some success with Java Native methods, so I believe such things can be done :0 Cheers! __________________________________________________ Do You Yahoo!? Yahoo! Auctions - Buy the things you want at great prices. http://auctions.yahoo.com/
Ronald Legere <rjljr2@yahoo.com> wrote,
Does anyone know of a tutorial introduction to the FFI? How does one go about getting started with this thing? Any simple examples?
Unfortunately, there is no tutorial style text about the FFI yet - I agree that it is necessary to have one, but nobody sat down and wrote one so far.
I just want to be able to do simple things (mostly access a c library from haskell... ok maybe not trivial :) ) I would be happy if I could just call c programs with simple types and pointers (no way am I going to figure out struct alignment! ).
Have you had a look at the various tools that simplify calling C code? (The do stuff like figuring out struct alignment automatically.) There are four tools by now (in order of increasing complexity and sophistication): (1) hsc2hs: Comes with new versions of GHC. (2) c2hs: http://www.cse.unsw.edu.au/~chak/haskell/c2hs/ (3) greencard: http://haskell.org/greencard/ (4) hdirect: http://haskell.org/hdirect/ You see - the Haskell developers believe in choice ;-) Cheers, Manuel
--- "Manuel M. T. Chakravarty" <chak@cse.unsw.edu.au> wrote: ** about the various interface generators
You see - the Haskell developers believe in choice ;-)
Cheers, Manuel
I guess I have mixed feelings about all the choices. Choices mean you can pick the best one for the job, but it also means more to learn. Which also is good and bad :):) I suppose for the moment I will try to HDirect and KDirect, as I would like to get a bit into understanding how TCLhaskell is implemented. Cheers! Thanks again for the pointers,Wojciech and Manuel ! __________________________________________________ Do You Yahoo!? Get email at your own domain with Yahoo! Mail. http://personal.mail.yahoo.com/?.refer=text
On Sat, 10 Mar 2001, Ronald Legere wrote:
Does anyone know of a tutorial introduction to the FFI? How does one go about getting started with this thing? Any simple examples? I just want to be able to do simple things (mostly access a c library from haskell... ok maybe not trivial :) ) I would be happy if I could just call c programs with simple types and pointers (no way am I going to figure out struct alignment! ). I have had some success with Java Native methods, so I believe such things can be done :0
Cheers!
Try KDirect - it is relatively simple and the tutorial is present. On the other hand, it isn't very powerful - yet it may satisfy you. http://www.astercity.net/~khaliff/haskell/kdirect Wojciech Moczydlowski, Jr
participants (6)
-
Levent Erkok -
Manuel M. T. Chakravarty -
qrczak@knm.org.pl -
Ronald Legere -
Simon Peyton-Jones -
Wojciech Moczydlowski, Jr