Gmail Calendar Documents Web Reader more »
Recently Visited Groups | Help | Sign in
Google Groups Home
"Man or boy" test
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  12 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Paolo Bonzini  
View profile  
 More options Nov 8 2007, 10:49 am
Newsgroups: comp.lang.haskell
From: Paolo Bonzini <bonz...@gnu.org>
Date: Thu, 08 Nov 2007 15:49:10 -0000
Local: Thurs, Nov 8 2007 10:49 am
Subject: "Man or boy" test
>From Wikipedia: The man or boy test was proposed by computer scientist

Donald Knuth as a means of evaluating implementations of the ALGOL 60
programming language. The aim of the test was to distinguish compilers
that correctly implemented "recursion and non-local references" from
those that did not.

        I have written the following simple routine, which may separate the
        "man-compilers" from the "boy-compilers" - Donald Knuth.

Here is the original ALGOL 60 program by Knuth:

begin
  real procedure A (k, x1, x2, x3, x4, x5);
  value k; integer k;
  begin
    real procedure B;
    begin k:= k - 1;
          B:= A := A (k, B, x1, x2, x3, x4);
    end;
    if k <= 0 then A:= x4 + x5 else B;
  end;
  outreal (A (10, 1, -1, -1, 1, 0));
end;

Here is a possibly more readable Smalltalk program (the only language
I know well that has all the requested features):

Integer>>manOrBoy
    "Smalltalk primer: [1] is a lambda, in Haskell it would be a ()-

>Number"

    ^self x1: [1] x2: [-1] x3: [-1] x4: [1] x5: [0]

Integer>>x1: x1 x2: x2 x3: x3 x4: x4 x5: x5
    | b k |
    k := self.
    "b is a closure, so it uses and modifies the value of k from the
enclosing environment"
    b := [ k := k - 1. k x1: b x2: x1 x3: x2 x4: x3 x5: x4 ].
    ^k <= 0 ifTrue: [ x4 value + x5 value ] ifFalse: b

"Example: '10 manOrBoy' returns -67"

What could be an Haskell implementation of this thing???

Thanks in advance,

Paolo


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ingo Wechsung  
View profile  
 More options Nov 9 2007, 3:08 am
Newsgroups: comp.lang.haskell
From: Ingo Wechsung <quetzalc...@consultant.com>
Date: Fri, 09 Nov 2007 00:08:55 -0800
Local: Fri, Nov 9 2007 3:08 am
Subject: Re: "Man or boy" test
On 8 Nov., 16:49, Paolo Bonzini <bonz...@gnu.org> wrote:

This is hard to tell for people like me that are not familiar with
ALGOL calling conventions.

    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Paolo Bonzini  
View profile  
 More options Nov 9 2007, 4:53 am
Newsgroups: comp.lang.haskell
From: Paolo Bonzini <bonz...@gnu.org>
Date: Fri, 09 Nov 2007 09:53:39 -0000
Local: Fri, Nov 9 2007 4:53 am
Subject: Re: "Man or boy" test

> This is hard to tell for people like me that are not familiar with
> ALGOL calling conventions.

That's why I also posted the Smalltalk version.  Here is Lisp,
but it uses setq.  I figure in Haskell you'd use a State monad,
but there are probably other ways.

(defun manOrBoy (x)
  (manOrBoy-func x (lambda () 1) (lambda () -1)
                   (lambda () -1) (lambda () 1)
                   (lambda () 0)))

(defun manOrBoy-func (k-param x1 x2 x3 x4 x5)
  (let*
    ((k k-param)
     (b
      (lambda (f)
        (lambda ()
          (progn
            (setq k (- k 1))
            (manOrBoy-func k (funcall b b) x1 x2 x3 x4))))))
    (if (<= k 0)
        (+ (funcall x4) (funcall x5))
      (funcall (funcall b b)))))


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ingo Wechsung  
View profile  
 More options Nov 9 2007, 5:25 am
Newsgroups: comp.lang.haskell
From: Ingo Wechsung <quetzalc...@consultant.com>
Date: Fri, 09 Nov 2007 02:25:53 -0800
Local: Fri, Nov 9 2007 5:25 am
Subject: Re: "Man or boy" test
On 9 Nov., 10:53, Paolo Bonzini <bonz...@gnu.org> wrote:

> > This is hard to tell for people like me that are not familiar with
> > ALGOL calling conventions.

> That's why I also posted the Smalltalk version.

This is like you first wrote chinese and now that I tell you I
understand chinese only partly, you post japanese.

>  Here is Lisp,

And now you continue with Klingon :)

> I figure in Haskell you'd use a State monad,

Seems like overkill.

Let me try.

fA k x1 x2 x3 x4 x5 = let
    fB = let
            k' = k-1
         in fA k' fB x1 x2 x3 x4
  in if k < 0 then x4 + x5 else fB

Untested.


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Vesa Karvonen  
View profile  
 More options Nov 9 2007, 5:32 am
Newsgroups: comp.lang.haskell
From: Vesa Karvonen <vesa.karvo...@cs.helsinki.fi>
Date: 9 Nov 2007 10:32:55 GMT
Local: Fri, Nov 9 2007 5:32 am
Subject: Re: "Man or boy" test

Ingo Wechsung <quetzalc...@consultant.com> wrote:
> On 9 Nov., 10:53, Paolo Bonzini <bonz...@gnu.org> wrote:
> > > This is hard to tell for people like me that are not familiar with
> > > ALGOL calling conventions.

> > That's why I also posted the Smalltalk version.
> This is like you first wrote chinese and now that I tell you I
> understand chinese only partly, you post japanese.
> >  Here is Lisp,
> And now you continue with Klingon :)

See the link for my SML translations:

  http://lambda-the-ultimate.org/node/1309#comment-14814

> > I figure in Haskell you'd use a State monad,
> Seems like overkill.

I'm afraid you will need mutable refs to properly encode the Man or
Boy Test.

-Vesa Karvonen


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Paul Rubin  
View profile  
 More options Nov 9 2007, 5:33 am
Newsgroups: comp.lang.haskell
From: Paul Rubin <http://phr...@NOSPAM.invalid>
Date: 09 Nov 2007 02:33:57 -0800
Local: Fri, Nov 9 2007 5:33 am
Subject: Re: "Man or boy" test

Ingo Wechsung <quetzalc...@consultant.com> writes:
> > I figure in Haskell you'd use a State monad,
> Seems like overkill.
> Let me try.

I don't think you can do it like that, without mutation.  Algol 60
uses call-by-name and the test is of whether mutating the parameters
works properly.

    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Dirk Thierbach  
View profile  
 More options Nov 9 2007, 5:28 am
Newsgroups: comp.lang.haskell
From: Dirk Thierbach <dthierb...@usenet.arcornews.de>
Date: Fri, 9 Nov 2007 11:28:17 +0100
Local: Fri, Nov 9 2007 5:28 am
Subject: Re: "Man or boy" test

Paolo Bonzini <bonz...@gnu.org> wrote:
>>From Wikipedia: The man or boy test was proposed by computer scientist
> Donald Knuth as a means of evaluating implementations of the ALGOL 60
> programming language. The aim of the test was to distinguish compilers
> that correctly implemented "recursion and non-local references" from
> those that did not.

For the appropriate values of "correctly" and that time.

> Here is the original ALGOL 60 program by Knuth:

> begin
>  real procedure A (k, x1, x2, x3, x4, x5);
>  value k; integer k;
>  begin
>    real procedure B;
>    begin k:= k - 1;
>          B:= A := A (k, B, x1, x2, x3, x4);
>    end;
>    if k <= 0 then A:= x4 + x5 else B;
>  end;
>  outreal (A (10, 1, -1, -1, 1, 0));
> end;
> What could be an Haskell implementation of this thing???

Haskell is a pure language, so the impure effects of updating k must
be wrapped in a state monad.

import Control.Monad.ST
import Data.STRef

type S s = ST s Integer

a :: Integer -> S s -> S s -> S s -> S s -> S s -> S s
a k x1 x2 x3 x4 x5 = a' where
  a' | k <= 0    = do { x4' <- x4; x5' <- x5; return (x4' + x5') }
     | otherwise = do { kr <- newSTRef k; b kr }
  b kr = do
    k <- readSTRef kr
    let k' = k - 1
    writeSTRef kr k'
    a k' (b kr) x1 x2 x3 x4

run k =
  runST (a k (return 1) (return (-1)) (return (-1)) (return 1) (return 0))

Note that in the presence of side effects, the ambigous expression "x4 + x5"
must be given explicit evaluation order (left argument first, or right
argument first). In this case, it makes no difference; in general, it can.

Result:

*Main> run 10
-67
*Main> run 9
-30

> Here is a possibly more readable Smalltalk program (the only language
> I know well that has all the requested features):

Any language should be able to simulate the "requested features"
(closures and side-effects), even if they are not primary language
constructs. (Yes, I'm getting really tired of language wars).
I could write the above program even in C.

OTOH, if Wikipedia is right and Knuth himself wasn't able to calculate
the correct answer, I think this shows clearly that ugly nested
side-effects like these can easily lead to confusion, and not to
clearly readable and correct programs.

- Dirk


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Vesa Karvonen  
View profile  
 More options Nov 9 2007, 6:15 am
Newsgroups: comp.lang.haskell
From: Vesa Karvonen <vesa.karvo...@cs.helsinki.fi>
Date: 9 Nov 2007 11:15:26 GMT
Local: Fri, Nov 9 2007 6:15 am
Subject: Re: "Man or boy" test
Dirk Thierbach <dthierb...@usenet.arcornews.de> wrote:

[...]

> OTOH, if Wikipedia is right and Knuth himself wasn't able to calculate
> the correct answer, I think this shows clearly that ugly nested
> side-effects like these can easily lead to confusion, and not to
> clearly readable and correct programs.

Errare Humanum Est.

I think that the biggest obstacle to "understanding" the Man or Boy
Test is the arbitrary and artificial nature of the program.  It is
easy to write much more convoluted programs without using any
side-effects.  In either case, pure or impure, calculating the correct
answer is a mechanical exercise.

-Vesa Karvonen


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ingo Wechsung  
View profile  
 More options Nov 9 2007, 6:51 am
Newsgroups: comp.lang.haskell
From: Ingo Wechsung <quetzalc...@consultant.com>
Date: Fri, 09 Nov 2007 03:51:46 -0800
Local: Fri, Nov 9 2007 6:51 am
Subject: Re: "Man or boy" test
On 9 Nov., 11:33, Paul Rubin <http://phr...@NOSPAM.invalid> wrote:

> Ingo Wechsung <quetzalc...@consultant.com> writes:
> > > I figure in Haskell you'd use a State monad,
> > Seems like overkill.
> > Let me try.

> I don't think you can do it like that, without mutation.  Algol 60
> uses call-by-name and the test is of whether mutating the parameters
> works properly.

I see. Works of the devil :)
The trick seems to be that every mention of B should decrease *the
same* k.
But if this is so, the declaration as "value" is clearly a misnomer,
isn't it?

    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Paolo Bonzini  
View profile  
 More options Nov 9 2007, 7:39 am
Newsgroups: comp.lang.haskell
From: Paolo Bonzini <bonz...@gnu.org>
Date: Fri, 09 Nov 2007 12:39:11 -0000
Local: Fri, Nov 9 2007 7:39 am
Subject: Re: "Man or boy" test

> > Here is a possibly more readable Smalltalk program (the only language
> > I know well that has all the requested features):

> Any language should be able to simulate the "requested features"
> (closures and side-effects), even if they are not primary language
> constructs. (Yes, I'm getting really tired of language wars).
> I could write the above program even in C.

Sure, I should have written "the only language I know well where
I do not need to simulate the requested features".  Also notice
that I wrote "the only language I know *well*", not "the only
language on Earth".  It was not meant to be a language war.

That said, thanks for the answer.

Paolo


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Laurent Deniau  
View profile  
 More options Nov 9 2007, 10:56 am
Newsgroups: comp.lang.haskell
From: Laurent Deniau <Laurent.Den...@gmail.com>
Date: Fri, 09 Nov 2007 07:56:34 -0800
Local: Fri, Nov 9 2007 10:56 am
Subject: Re: "Man or boy" test
On 9 nov, 11:28, Dirk Thierbach <dthierb...@usenet.arcornews.de>
wrote:

Now that I see it in Haskell, I can write it in C ;-)

> time man-or-boy 10

-67
0.000s
> time man-or-boy 9

-30
0.000s
> time man-or-boy 24

-4268854
1.760s

Looks like it uses an exponential amount of memory...

a+, ld.

/* man-or-boy.c */
#include <stdio.h>
#include <stdlib.h>

// --- thunks
typedef struct arg {
  int       (*fn)(struct arg*);
  int        *k;
  struct arg *x1, *x2, *x3, *x4, *x5;

} ARG;

// --- lambdas
int eval(ARG* a) { return a->fn(a); }
int f_1 (ARG* _) { return -1; }
int f0  (ARG* _) { return  0; }
int f1  (ARG* _) { return  1; }

// --- helper
#define ARG(...) (&(ARG){ __VA_ARGS__ })
#define FUN(...) ARG(B,&k,__VA_ARGS__)

// --- functions
int B(ARG* a) {
  int A(ARG*);
  int k = *a->k -= 1;
  return A( FUN(a,a->x1,a->x2,a->x3,a->x4) );

}

int A(ARG* a) {
  return *a->k <= 0 ? eval(a->x4)+eval(a->x5) : B(a);

}

int main(int argc, char **argv) {
  int k = argc == 2 ? strtol(argv[1],0,0) : 10;
  printf("%d\n", A( FUN(ARG(f1),ARG(f_1),ARG(f_1),ARG(f1),ARG(f0)) ));


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jed Davis  
View profile  
 More options Nov 9 2007, 11:44 am
Newsgroups: comp.lang.haskell
From: Jed Davis <j...@panix.com>
Date: Fri, 09 Nov 2007 11:44:33 -0500
Local: Fri, Nov 9 2007 11:44 am
Subject: Re: "Man or boy" test

Ingo Wechsung <quetzalc...@consultant.com> writes:
> I see. Works of the devil :)
> The trick seems to be that every mention of B should decrease *the
> same* k.
> But if this is so, the declaration as "value" is clearly a misnomer,
> isn't it?

No, every activation of B will decrease the k in the activation of A
that created it.  The recursive call to A passes k by value, so any
B-ing done by the new A won't affect the old A's value.

Some of the mentions of B won't decrement anything at all, as their
thunks won't make it up to x4 or x5 to be forced before the
corresponding k runs out.

--
(let ((C call-with-current-continuation)) (apply (lambda (x y) (x y)) (map
((lambda (r) ((C C) (lambda (s) (r (lambda l (apply (s s) l))))))  (lambda
(f) (lambda (l) (if (null? l) C (lambda (k) (display (car l)) ((f (cdr l))
(C k)))))))    '((#\J #\d #\D #\v #\s) (#\e #\space #\a #\i #\newline)))))


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2010 Google