Hellow,


My colleague asked me to give an example of the 
                continuation passing style 
and demonstrate it in the form of Haskell program.
I had a naive idea that Haskell should understand any lambda-
expression. So I proposed the following example of the list length 
function:

l =  \xs c -> if null xs then 0  else  1+(c (tail xs) c)

lng xs =  l xs l

But Haskell refused to find the type for `c'.

So there had arised a question of mere curiosity of how to make him 
understand it.
We introduced     data  C a = C ([a] -> C a -> Int) ,

changed `lng' respecively to deal with this `C', and made `lng' work.

My questions, as the are summarized by   
                      Yoshihiko Ichikawa  ( [EMAIL PROTECTED] )  
are the following.

1. Why the Haskell type system does not allow recursive type equation? 
   And, if so, what is the real hindrance, or what would happen if the
   solver exists?
2. What is the relationship among the untyped lambda calculus,
   the simply typed lambda calculus and the Haskell typing system?
   Does the type system allows programmers to define a fixed point
   combinator of type (a->a)->a without using recursive function
   defintion?
3. If it is impossible, which kind of fixed point combinators
   can be definable in Haskell?

Personanly, I am asking only the question (1).
For example, why Haskell cannot introduce this 
                data  C a = C ([a] -> C a -> Int)
itself ?
For it manages to solve the recursive equations for the functions,
why cannot it solve types - in the simple cases ?

I do not agree to use the fix point combinator Y (fix) - unless we 
express it as a pure lambda too in Haskell.
I failed to invent the acceptable type for Y - in the manner it was 
done for `length' in Haskell.
Though I did not try much. Maybe it is impossible ?

Below follows certain discussion.

The Haskell list correspondents are invited with their comments.


Regards,

Sergey Mechveliani  [EMAIL PROTECTED]





--------------------------------------------------------------------
--------------------------------------------------------------------
Yoshihiko Ichikawa  ([EMAIL PROTECTED])  writes

I'm negative about the definability of Y in the Haskell type system,
altough I cannot prove it.  (See appendix 3 for a problem raised by
assuming a general purpose recursive type solver).

<skipped ...>

Appendix 1.

Because of the morphism,    Lambda =~= Lambda -> Lambda
the type of lambda terms should have types such as:

        data Lambda = L (Lambda -> Lambda)

And the isomorphism between Lambda and Lambda -> Lambda are established
by the following two functions:
        lambdaApp :: Lambda -> Lambda -> Lambda
        lambdaApp (L x) y = x y
        absLambda :: (Lambda -> Lambda) -> Lambda
        absLambda fun = L fun

Intuitively, in Lisp, absLambda may correspond to #'(lambda ....) and,
lambdaApp may correspond to funcall. 

Then, the rest of the constuction is very simple.   Consider a definition
of the fixed point combinator (by Turing):

             Y == ZZ, where Z == \zx.x(zzx)

First, zTuring is defined as follows:

        zTuring :: Lambda
        zTuring
           = absLambda (\z ->
                absLambda (\x -> lambdaApp x (lambdaApp (lambdaApp z z) x)))

So, yTuring can be defined simply apply zTuring to itself:

        yTuring :: Lambda
        yTuring = lambdaApp zTuring zTuring

There is no recursion here, and if you want, you can write down yTuring
without using function names.

...

How to play with the Lambda type.

The K operator defined as \xy.x is now:

        kOp = absLambda (\x -> absLambda (\y -> x))

Consider the D-operator which have the following property:
                Dxy0 = x
                Dxyn = y,  if n /= 0
where 0 and n are church numerals, \xy.y and \xy.x(x(....(xy))), respctively.
                                                -----------
                                                  n times 
By this setting, we can play a simple if-then-else game:

<skipped ...>

Arithmetic operations can also be defined using known operators.

I'm not testing the full properties of the above setting.  So, 
you might find more interesting style of the game. 
...
And, writing a meaningful example using yTuring will be a hard work.

-------------------------------------------------------------------
-------------------------------------------------------------------
Sergey Mechveliani  ([EMAIL PROTECTED]):


Thank you. I guess, this  yTuring  is what it is needed.

And let the data (lists and numbers) be reprersented as the lambda-s.
So all the type here are inhabited, are they ?

And what the Haskell people would say ?

-------------------------------------------------------------------
-------------------------------------------------------------------

Yoshihiko Ichikawa  ([EMAIL PROTECTED]) :

Please notice that `error "something"' denotes a bottom.
Hence, even if some expression like yTuring can be defined in Haskell,
the expression at last may represent a bottom.  The ``game'' I wrote 
is played, just because `error ...' has a side-effect, i.e., printing a 
message.  For another example, there is `trace' in Glasgow Haskell.
The function is of type
                       _trace :: String -> a -> a
and, an expression, 
                    let bottom = bottom 
                    in trace "enter into a closure" bottom

denotes a bottom, but having the side-effect which prints a message.

So, even if you may define lamabda-terms, things would vanish
once you try to get represented values. 

> And what the Haskell people would say ?

That's difficult to guess (^^;



Reply via email to