RE: no continuations

2004-01-09 Thread Kevin S. Millikin
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

2004-01-01 Thread Kevin S. Millikin
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

2003-12-30 Thread Kevin S. Millikin
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

2003-12-30 Thread Kevin S. Millikin
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

2003-08-14 Thread Kevin S. Millikin
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

2003-07-30 Thread Kevin S. Millikin
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

2003-07-09 Thread Kevin S. Millikin
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?

2003-06-27 Thread Kevin S. Millikin
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++

2003-02-03 Thread Kevin S. Millikin
 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

2003-01-31 Thread Kevin S. Millikin
 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

2003-01-24 Thread Kevin S. Millikin
 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

2003-01-24 Thread Kevin S. Millikin
 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

2003-01-24 Thread Kevin S. Millikin
 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

2003-01-17 Thread Kevin S. Millikin
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

2002-12-06 Thread Kevin S. Millikin
 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