RE: no continuations
On Friday, January 09, 2004 2:48 AM, Ashley Yakeley [SMTP:[EMAIL PROTECTED] wrote: Do you have an example of use of Y for letrec where a program would violate R5RS? Sure, take a look at my implementation of Ben Rudiak-Gould's implementation of Alan Bawden's implementation of boxes. In 4.2.2 of R5RS, it says, re letrec: Semantics: The variables are bound to fresh locations holding undefined values, the inits are evaluated in the resulting environment (in some unspecified order), each variable is assigned to the result of the corresponding init, the body is evaluated in the resulting environment, and the value(s) of the last expression in body is(are) returned. Each binding of a variable has the entire `letrec' expression as its region, making it possible to define mutually recursive procedures. The result of the corresponding init is *assigned to* each variable (anyone know why the wording is backward above?), and that is after the inits are evaluated, which is after the variables are bound. There was a discussion on comp.lang.scheme a couple of years ago about this. http://groups.google.com/groups?hl=enlr=ie=UTF-8oe=UTF-8th=fdcf3 554852a3cadseekm=3AC66F16%40MailAndNews.com#link1 http://groups.google.com/groups?hl=enlr=ie=UTF-8oe=UTF-8th=a47e0 3e456b2dc2aseekm=200102220358.TAA77339%40adric.cs.nps.navy.mil#link1 http://groups.google.com/groups?hl=enlr=ie=UTF-8oe=UTF-8th=58a68 6525be78d16rnum=1 ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: no continuations
On Tuesday, December 30, 2003 5:04 PM, Kevin S. Millikin [SMTP:[EMAIL PROTECTED] wrote: Oh, sure. I didn't mean to quibble with the idea that continuations are computational effects. Just wanted to point out that (I think) you can't macro express mutation with call/cc, unless you've already got mutation anyway. [snip] Yup. If you do that, you can use d as your setter and c as your getter: (define c (make-cell)) (define d c) ((d 'set) 9) (c 'get) 9 ((d 'set) 17) (c 'get) 17 It sure looks like the example contradicts the assertion, but I happen to know that there is a set! (or some other assignment) in the macro expansion of define. I'm just using call/cc to get at that, rather than getting at the one in the expansion of letrec. Moved to Haskell Cafe. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: no continuations
On Tuesday, December 30, 2003 12:39 PM, Ben Rudiak-Gould [SMTP:[EMAIL PROTECTED] wrote: With letrec and unrestricted call/cc you can implement ML-style refs: With an *implementation of letrec that uses mutation* and unrestricted call/cc, you can implement ML-style ref cells: Petite Chez Scheme Version 6.0a Copyright (c) 1998 Cadence Research Systems (define-syntax letrec^ (syntax-rules () ((_ ((Var Exp)) Body Bodies ...) (let ((Y (lambda (f) ((lambda (g) (f (g g))) (lambda (g) (f (lambda (x) ((g g) x (let ((Var (Y (lambda (Var) Exp Body Bodies ...) (letrec^ ((fact (lambda (n) (if (zero? n) 1 (* n (fact (- n 1))) (fact 5)) 120 (define (make-cell) (call/cc (lambda (return-from-make-cell) (letrec^ ((state (call/cc (lambda (return-new-state) (return-from-make-cell (lambda (op) (case op ((set) (lambda (value) (call/cc (lambda (return-from-access) (return-new-state (list value return-from-access)) ((get) (car state) ((cadr state) 'done) (define c (make-cell)) ((c 'set) 3) (c 'get) 3 ((c 'set) 7) done (c 'get) 3 ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
RE: no continuations
On Tuesday, December 30, 2003 3:10 PM, Ben Rudiak-Gould [SMTP:[EMAIL PROTECTED] wrote: Interesting. This still violates referential transparency, though. (c 'get) returns a value or errors out depending on whether (c 'set) has been called yet. Oh, sure. I didn't mean to quibble with the idea that continuations are computational effects. Just wanted to point out that (I think) you can't macro express mutation with call/cc, unless you've already got mutation anyway. And take a look at this! (define c (make-cell)) (define d c) ((d 'set) 9) (d 'get) Error in car: #procedure is not a pair. Type (debug) to enter the debugger. Something very nasty is going on here. I'm not sure exactly what it is, but I think at least one of the define statements is getting executed at least twice. Yup. If you do that, you can use d as your setter and c as your getter: (define c (make-cell)) (define d c) ((d 'set) 9) (c 'get) 9 ((d 'set) 17) (c 'get) 17 Does this help?: (define c (let ((cell (make-cell))) (display Hi, Ben.) (newline) cell)) Hi, Ben. (define d c) ((d 'set) 9) Hi, Ben. ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
RE: IO Bool - Bool
On Wednesday, August 13, 2003 11:20 PM, Tn X-10n [SMTP:[EMAIL PROTECTED] wrote: is it possible to convert IO Bool to Bool? Sure. Which Bool do you want? True? toTrue :: IO Bool - Bool toTrue x = True Or False? toFalse :: IO Bool - Bool toFalse x = False Maybe that's not what you had in mind. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: Useful list output function
On Wednesday, July 30, 2003 1:52 PM, Shawn P. Garbett [SMTP:[EMAIL PROTECTED] wrote: output :: (a - IO b) - [a] - IO () output f = (foldr () (return ())).(map f) Study the Prelude :) output :: (a - IO b) - [a] - IO () output = mapM_ ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: passing a Handle to a C function
Hal, I was really hoping that someone would have a pretty answer for you by now. Just this last week, I came up with a similar problem--I need to pass a handle to some foreign code, but in my case, the foreign code can treat the handle as opaque, it just needs to be able to give it back to Haskell when needed. I haven't actually solved my problem in a nice way (though your posted code suggests a way, using the file descriptor). foreign import ccall myHFile.h myCFun c__myCFun :: Ptr CInt - IO () myCFun :: Handle - IO () myCFun (FileHandle handleMV) = do h__ - readMVar handleMV ptr - malloc poke ptr (toCInt $ haFD h__) c__initVars ptr Do you mean c__myCFun instead of c__initVars? What is toCInt? Is it doing anything wierd? Anyway, might this work? foreign import ccall myHFile.h myCFun_stub c__myCFun :: CInt - IO () myCFun :: Handle - IO () myCFun (FileHandle handleMV) = readMVar handleMV = c__myCFun . toCInt . haFD To pass a CInt (no need for Ptr here) to a stub function in C, where the stub function just converts the file descriptor to a FILE * and calls yourCFun (I mean, myCFun): void myCFun_stub(int fd) { FILE *f = fdopen(fd, w); myCFun(f); fflush(f); } It worked for writing to a text file in a simple test, and for writing to stdout. I needed to fflush on the C side when writing to the file. Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x162 http://www.atcorp.com ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Win32 dlls -- how to do it?
ac New to Haskell, new to GHC. My initial intention in picking up ac Haskell is to be able to write some functions in Haskell and then ac compile them into .dlls for Win32 that I can call from programs ac written in other languages. So before I get too deeply invested I ac want to make sure that is possible. It's certainly possible. I do it here all the time on a commercial project. I even volunteered a few months ago to write some better documentation, but I sadly have not had the time to do it. As Sigbjorn says, adding -package base when linking the DLL with ghc will silence those errors from the linker. The warning given when compiling the C code in dllMain.c comes from the declaration of __stginit_Adder as EXTFUN(__stginit_Adder) Which is not really the type that startupHaskell expects. Declare it instead as extern void __stginit_Adder(void); and the warning will be silenced. The much bigger gotcha is that the code in dllMain.c from Sect 11 of the user's guide will probably not work, because Windows forbids certain things from happening in dllMain (basically, anything that could possibly cause one to reattach to the DLL). That includes creating new threads, and that includes creating timers, and startupHaskell tries to do that. I don't remember at the moment if it is a problem when the GHC runtime is in a separate DLL, but it is certainly a problem when linking the GHC runtime into the same DLL. My typical solution is to provide entry points to explicitly startup and shutdown the Haskell runtime, outside of a call to dllMain. Here is an example, calling Adder from Java: 1. Write some Haskell code to implement the add function in the DLL. Note that Java will expect a mangled name, which we supply manually: Adder.hs module Adder (add) where import Foreign (Ptr, Int32) data JNIEnv data JClass foreign export stdcall Java_Adder_add add :: Ptr JNIEnv - Ptr JClass - Int32 - Int32 - IO Int32 add :: Ptr JNIEnv - Ptr JClass - Int32 - Int32 - IO Int32 add _ _ m n = return (m + n) 2. Compile. Don't forget -fglasgow-exts: ghc -fglasgow-exts -c Adder.hs 3. Write C functions that can be called by Java (mangling the names again) and that can be used to startup and shutdown the Haskell runtime. You can't do this directly from Java, because the FFI functions don't have the mangled names that Java expects, and you can't do it from Haskell code for obvious reasons. ccode.c #include jni.h #include HsFFI.h extern void __stginit_Adder(void); static char *args[] = { ghcDll, 0 }; static int argc = 1; static char **argv = args; JNIEXPORT void JNICALL Java_Adder_haskellInit(JNIEnv *e, jclass c) { hs_init(argc, argv); hs_add_root(__stginit_Adder); } JNIEXPORT void JNICALL Java_Adder_haskellExit(JNIEnv *e, jclass c) { hs_exit(); } 4. Compile it. JAVAHOME is presumed to be set to the root of your Java install (the directory containing the include subdirectory): ghc -I$JAVAHOME/include -I$JAVAHOME/include/win32 -optc -mno-cygwin -c ccode.c 5. Link into DLL, using ghc (I generally call dllwrap directly, because it gives me finer (actually, just less verbose) control over DLL options): ghc --mk-dll -optdll --add-stdcall-alias -o adder.dll Adder.o Adder_stub.o ccode.o -package base -optdll --add-stdcall-alias is important, because Java can't find the entries otherwise. 6. Write a Java driver that loads the native library (the DLL), initializes the Haskell runtime, calls our simple DLL function, and then shutdowns the Haskell runtime: Adder.java public class Adder { static { System.loadLibrary(adder); haskellInit(); } public static native void haskellInit(); public static native void haskellExit(); public static native int add(int m, int n); public static void main(String[] args) { try { System.out.println(Answer is: + Adder.add(32, 10)); } finally { haskellExit(); }}} 7. Compile the Java code: javac -classpath . Adder.java 8. Enjoy: java -classpath . Adder Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x162 http://www.atcorp.com ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: GHC and C++
Simon == Simon Peyton-Jones [EMAIL PROTECTED] writes: SimonWould either of you like Simon to write up some stand-alone notes that explain how to do Simon it, and what the pitfalls are? You can make suggestions Simon for improving GHC too! I'd be happy to take a first stab at a write-up. It's not a trivial exercise--the Microsoft, Borland, and GNU compilers do not agree on a naming scheme for symbols exported from DLL's. -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Calling ghc dll's with MSVC++ code
Sigbjorn == Sigbjorn Finne [EMAIL PROTECTED] writes: Sigbjorn That's the system trap interrupt (i.e., transition to Sigbjorn ring 0 / kernel mode to perform a system call/service.) Thanks! I've learned more about Windows and DLLs in a few days than I ever expected or wanted to. The problem appears to be related to http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b153867 and http://support.microsoft.com/default.aspx?scid=kb%3bEN-US%3b142243 int 0x2e is (presumably) an attempt to attach to the (my) DLL. DllMain is (by design) not reentrant. An attempt to create a thread from DllMain would attach to the DLL, calling DllMain with a reason of DLL_THREAD_ATTACH. This latter call will hang until the original call returns (which will never happen, now). timeSetEvent creates a new thread; and the callback is in the same DLL as the call to startupHaskell. The workaround appears to be to not put code that might possibly create a new thread (that needs the DLL) in DllMain; instead such code should go in an initialization function that is called after DllMain returns. I'll test it out and post code that corrects the example from the User's Guide. -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Lazy evaluation alternative
Chris == Chris Clearwater [EMAIL PROTECTED] writes: Chris But also, this brings me to another idea! Data structures Chris should be built from lambdas and CPS! For example, a list Chris of integers: 1 : 2 : 3 Chris list = \c - c 1 (\c - c 2 nil) How about just: cons hd tl = \ c - c hd tl then we could write the usual accessors: head xs = xs (\ hd tl - hd) tail xs = xs (\ hd tl - tl) This is a very, very old idea. -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Lazy evaluation alternative
Chris == Chris Clearwater [EMAIL PROTECTED] writes: Chris LIAR. You want to steal my idea for yourself! It's MINE! :) I hate to be the one to break it to you, but we used to routinely show this trick to Intro to CS students. Chris But anyways, it was to show that when a list is defined Chris like that, (natural m) becomes a list itself because it is Chris of the form: \c - c hd tl after partial evaluation. Yes. But it's not the CPS that delays evaluation, it's just the lambda. Switching to a strict language, Scheme, one would write: (define ones (lambda () (cons 1 ones))) Explicitly delaying the evaluation of (cons 1 ones) by putting it under a lambda. We *could* perform the CPS translation, but it's not necessary to delay evaluation, lambda does that all by itself. ones #procedure (ones) (1 . #procedure) (cdr (ones)) #procedure ((cdr (ones))) (1 . #procedure) Of course, if we wanted *lazy* evaluation, we would want to avoid performing the cons more than once if it is demanded more than once. We have to use something other than lambda for that: (define ones (delay (begin (printf forcing...~n) (cons 1 ones ones #procedure (force ones) forcing... (1 . #procedure) (force ones) (1 . #procedure) (cdr (force ones)) #procedure (force (cdr (force ones))) (1 . #procedure) Notice how many times (cons 1 ones) got evaluated. So your trick *is* used to implement lazy evaluation in other languages. It's not very pleasant if you write a lot of lazy code, because you have to explicitly suspend evaluation of values using delay and explicitly demand evaluation using force. Thus, we have lazy languages that make the laziness implicit. -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com ___ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell
Re: Lazy evaluation alternative
Chris == Chris Clearwater [EMAIL PROTECTED] writes: Chris Sarcasm, Kevin, sarcasm. :) Why is it that those who most need to point out that they were joking are least able to see it in others? Chris The difference is with the CPS way it is implicit. For Chris example take the Y combinator written using both methods Chris (again this is pseduo code, not intended to be real haskell Chris code or run in hugs) That's a funny definition of implicit. All you need to delay evaluation is lambda. You're performing a CPS transformation as a way to insert a lambda in the proper place. BUT THAT'S NOT NECESSARY. Just write the lambda where you want it. You don't need to abstract over a continuation to delay evaluation, you can abstract over anything at all (it doesn't matter what). And you only ever apply the most recent continuation (notice how you could use the identifier c for every one of your continuations?). You don't have to apply c to pass a value to the current continuation, there's alread a way to do that: just return the value. Chris Using the lambda way: Y f = f (lazy Y f) Then writing ones Chris would be something like: ones_fix f = 1:(force f) Chris Now the CPS way: Y f c = c (f (Y f)) Now writing ones: Chris ones_fix f c = c 1:f Your translation is wrong. Here's the correct lambda way (in the same pseudo functional language): Y f = \ () - f (Y f) where I didn't presume any delay or lazy macro. Here's ones_fix: ones_fix f = \ () - 1 : f Compare to: Y f = \ c - c (f (Y f)) ones_fix f = \ c - c (1 : f) Which one seems to be more implicit? Where you abstract over a continuation to delay evaluation, I abstract over anything I feel like. Where you apply a continuation to a value, I just return a value. Where you would pass in a continuation to a CPSed function, I would just apply the result to some suitable token (unless I had zero argument functions) (that is, I would force an expression wherever you would pass a continuation to a CPSed function). You've performed a CPS transformation, but you never do anything *interesting* with the continuation. That might suggest that, whatever you seem to have achieved, it didn't come from the CPS transformation. Chris Notice how the CPS way behaves as if it were actually Chris passed itself, while the lambda way behaves as if it were Chris passed itself quoted with lambda. The lambda way seems Chris like a hack while the CPS way feels consistant. I guess I don't understand. Change \ c - to \ () -. Remove the application of every c. Change occurrences of c in argument position to (). -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: Calling ghc dll's with MSVC++ code
Hmmm, I just now came across this: I'm not confident that creating Haskell DLLs is working at the moment. Has anyone else done it? I have. Or rather, I haven't. The example in Section 11.4 of the User's Guide doesn't work. The call to startupHaskell() hangs forever (or as long as I'm willing to wait). It works fine when the exact same call to startupHaskell is linked statically. Trouble is, there isn't yet a critical mass of DLL users to be sure that it works and stays working. Which is a bit of a chicken and egg problem. Windows programmers unite! Is two a critical mass? -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: AW: AW: Editor Tab Expansion
Ingo == Ingo Wechsung [EMAIL PROTECTED] writes: Ingo Or, to turn it another way: What you see is not necessarily Ingo what you get. This may be fine for ad hoc scripts that one Ingo examines in hugs. So is that the language's fault (because of what you get) or the editor's fault (because of what you see)? I'm guessing that what you see and what you get have *never* been identical for you, but you didn't care much, because they were indistinguishable. Now, with Haskell, that difference has become significant. And it's a (perhaps minor) problem. What is the cause of the problem? 1) Haskell makes the difference between what you see and what you get significant, it should not be that way 2) Your editor does not let you see what you're going to get, it should not be that way If you see the source of the problem as 1, you will likely choose the braces-semicolon route, or unfortunately (for you ;) ) not use Haskell. If you see it as 2, you will decide to reconfigure the editor you use for programming so that what you see *is* what you get. Ingo They used to do so, since Jan 1 1970 00:00 GMT, without real Ingo problems apart from pure formatting problems. The formatting Ingo problems will not go away with the advent of Haskell. But 2 Ingo new problems suddenly arise: syntax error due to formatting Ingo and formatting dependend semantic. And in exchange, two old problems suddenly went away: syntax errors due to incorrect bracketing or termination/separation, and formatting that was *not* significant (code that was formatted as if it did one thing but actually did another). -- Kevin S. Millikin Architecture Technology Corporation Research Scientist Specialists in Computer Architecture (952)829-5864 x. 162 http://www.atcorp.com ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe