Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-11 Thread Keean Schupke
Greg Buchholz wrote:
   Wow.  Color me impressed.  A little under a week ago, I stumbled
onto Joy, and thought to myself that it could be translated almost
directly into Haskell (which would imply it was possible to statically
type).  Well, it wasn't quite as direct as I had initially thought, but
it looks like you've done it.  Are there any papers/books out there
which I could study to learn more about these (and other) tricks of the
type system wizards? 
 

Here's a cleaned up version, I have made the function composition and 
stack both
use HLists... a bit neater. Have also added primrec and a 5th factorial.

As for type tricks most of these should be in the HList or OOHaskell 
papers. The things to notice are using types as instance labels, that 
constraints form horn
clause compile time meta-programs (in a non-backtracking prolog style) 
and that multi-parameter classes with functional depandencies simulate 
some dependant
types.

   Keean.
{-# OPTIONS -fglasgow-exts #-}
{-# OPTIONS -fallow-overlapping-instances #-}
{-# OPTIONS -fallow-undecidable-instances #-}

--Joy implemented in Haskell... extensible embedded language...

module Joy where

import MainGhcGeneric1

-- Building non-empty lists

type HOne = HSucc HZero
hOne :: HOne
hOne = undefined
type HTwo = HSucc HOne
hTwo :: HTwo
hTwo = undefined
type HThree = HSucc HTwo
hThree :: HThree
hThree = undefined

end :: HNil
end = hNil

instance HList s = Apply HNil s s where
	apply _ s = s
instance (HList s,HList s',HList l,Apply a s s',Apply l s' s'') = Apply (HCons a l) s s'' where
	apply (HCons a l) s = apply l (apply a s :: s')
instance HList s = Apply HZero s (HCons HZero s) where
	apply _ s = hCons hZero s
instance (HNat a,HList s) = Apply (HSucc a) s (HCons (HSucc a) s) where
	apply a s = hCons a s

data Lit a = Lit a
lit :: a - Lit a
lit a = Lit a
unl :: Lit a - a
unl (Lit a) = a
instance Show a = Show (Lit a) where
	showsPrec _ (Lit a) = showChar '[' . shows a . showChar ']'
instance HList s = Apply (Lit a) s (HCons a s) where
	apply (Lit a) s = hCons a s

class (HBool b,HList s) = HIfte b t f s s' | b t f s - s' where
	hIfte :: b - t - f - s - s'
instance (HList s,Apply t s s') = HIfte HTrue t f s s' where
	hIfte _ t _ s = apply t s
instance (HList s,Apply f s s') = HIfte HFalse t f s s' where
	hIfte _ _ f s = apply f s

data Ifte
ifte :: Ifte
ifte = undefined
instance Show Ifte where
	showsPrec _ _ = showString If
instance (Apply b s r,HHead r b',HIfte b' t f s s')
	= Apply Ifte (f :*: t :*: b :*: s) s' where
	apply _ (HCons f (HCons t (HCons b s))) = hIfte (hHead (apply b s :: r) :: b') t f s

data Nul
nul :: Nul
nul = undefined
instance Show Nul where
	showsPrec _ _ = showString Nul
instance HList s = Apply Nul (HCons HZero s) (HCons HTrue s) where
	apply _ (HCons _ s) = hCons hTrue s
instance HList s = Apply Nul (HCons (HSucc n) s) (HCons HFalse s) where
	apply _ (HCons _ s) = hCons hFalse s

data EQ
eq :: EQ
eq = undefined
instance Show EQ where
	showsPrec _ _ = showString Eq
instance (HList s,TypeEq a b t) = Apply EQ (HCons a (HCons b s)) (HCons t s) where
	apply _ (HCons a (HCons b s)) = hCons (typeEq a b) s

data Dip
dip :: Dip
dip = undefined
instance Show Dip where
	showsPrec _ _ = showString Dip
instance (HList s,HList s',Apply a s s') = Apply Dip (HCons a (HCons b s)) (HCons b s') where
	apply _ (HCons a (HCons b s)) = hCons b (apply a s)

data Dup 
dup :: Dup
dup = undefined
instance Show Dup where
	showsPrec _ _ = showString Dup
instance HList s = Apply Dup (HCons a s) (HCons a (HCons a s)) where
	apply _ s@(HCons a _) = hCons a s

data Pop
pop :: Pop
pop = undefined
instance Show Pop where
	showsPrec _ _ = showString Pop
instance HList s = Apply Pop (HCons a s) s where
	apply _ (HCons _ s) = s

data Swap
swap :: Swap
swap = undefined
instance Show Swap where
	showsPrec _ _ = showString Swap
instance HList s = Apply Swap (HCons a (HCons b s)) (HCons b (HCons a s)) where
	apply _ (HCons a (HCons b s)) = hCons b (hCons a s)

data Suc
suc :: Suc
suc = undefined
instance Show Suc where
	showsPrec _ _ = showString Suc
instance (HNat a,HList s) = Apply Suc (HCons a s) (HCons (HSucc a) s) where
	apply _ (HCons _ s) = hCons (undefined::HSucc a) s

data Pre
pre :: Pre
pre = undefined
instance Show Pre where
	showsPrec _ _ = showString Pre
instance (HNat a,HList s) = Apply Pre (HCons (HSucc a) s) (HCons a s) where
	apply _ (HCons _ s) = hCons (undefined::a) s

data Add
add :: Add
add = undefined
instance Show Add where
	showsPrec _ _ = showString Add
instance (HList s,HAdd a b c) = Apply Add (HCons a (HCons b s)) (HCons c s) where
	apply _ (HCons _ (HCons _ s)) = hCons (hAdd (undefined::a) (undefined::b)) s

class (HNat a,HNat b) = HAdd a b c | a b - c where
	hAdd :: a - b - c
instance HAdd HZero HZero HZero where
	hAdd _ _ = hZero
instance HNat b = HAdd HZero (HSucc b) (HSucc b) where
	hAdd _ b = b
instance HNat a = HAdd (HSucc a) HZero (HSucc a) where
	hAdd a _ = a
instance (HNat (HSucc a),HNat (HSucc b),HNat c,HAdd a b c)
	= HAdd 

Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-11 Thread Greg Buchholz
Keean Schupke wrote:
 The things to notice are using types as instance labels, that constraints
 form horn clause compile time meta-programs (in a non-backtracking prolog
 style) and that multi-parameter classes with functional depandencies simulate
 some dependant types.
 

I think I understood everything in that sentance up to the word as ;-)


Greg

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-09 Thread Keean Schupke
Greg Buchholz wrote:
Keean Schupke wrote:
 

I dont see why this is illegal... what do we want? take the top two 
items from the stack?
   

   With the code below (direct translation from tuples to HLists) I
still get an occurs check error when trying to define fact5...
 

Okay the reason is that types in the code end up depending on values. The
type of the stack changes when items are pushed or popped. So the type 
of the stack returned from recursive functions depends on the recursion 
count...

Haskell is not dependantly typed, so cannot deal with types that depend on
values. This is why your code with tuples, and the HList code (which is
really doing the same thing through a defined API) both fall down on the
recursion.
One solution is to make all elements the same type and use lists... like:
   data Elem = ElemInt Int | ElemChar Char...
But this looses any static type checking. The alternative is to lift the 
values
to the type level, using something like Peano numbers to represent naturals:

data HZero = HZero
data HSucc x = HSucc x
Now different values have explictly different types, so we can have types
which depend on them...
Attached is an example implementation of times using this technique 
and the
HList library (its not debugged... so there might be some mistakes).

   Keean.

{-# OPTIONS -fglasgow-exts #-}
{-# OPTIONS -fallow-overlapping-instances #-}
{-# OPTIONS -fallow-undecidable-instances #-}

module Joy where

import MainGhcGeneric1

data Lit a = Lit a 
instance Apply (Lit a) s (HCons a s) where
	apply (Lit a) s = HCons a s

data If = If
instance Apply t s s' = Apply If (HCons f (HCons t (HCons HTrue s))) s' where
	apply _ (HCons _ (HCons t (HCons _ s))) = apply t s
instance Apply f s s' = Apply If (HCons f (HCons t (HCons HFalse s))) s' where
	apply _ (HCons f (HCons _ (HCons _ s))) = apply f s

data Eq = Eq
instance TypeEq a b t = Apply Eq (HCons a (HCons b s)) (HCons t s) where
	apply _ (HCons a (HCons b s)) = HCons (typeEq a b) s

data Dip = Dip
instance Apply a s s' = Apply Dip (HCons a (HCons b s)) (HCons b s') where
	apply _ (HCons a (HCons b s)) = HCons b (apply a s)

data Dup = Dup
instance Apply Dup (HCons a s) (HCons a (HCons a s)) where
	apply _ s@(HCons a _) = HCons a s

data Pop = Pop
instance Apply Pop (HCons a s) s where
	apply _ (HCons _ s) = s

data Swap = Swap
instance Apply Swap (HCons a (HCons b s)) (HCons b (HCons a s)) where
	apply _ (HCons a (HCons b s)) = HCons b (HCons a s)

class (HNat a,HNat b) = HAdd a b c | a - b - c where
	hadd :: a - b - c
instance HAdd HZero HZero HZero where
	hadd _ _ = hZero
instance HAdd HZero (HSucc b) (HSucc b) where
	hadd _ b = b
instance HAdd a b c = HAdd (HSucc a) (HSucc b) (HSucc (HSucc c))
	hadd _ _ = hadd (undefined::a) (undefined::b)

data Add = Add
instance HAdd a b c = Apply Add (HCons a (HCons b s)) (HCons c s) where
	apply _ (HCons _ (HCons _ s)) = HCons (hadd (undefined::a) (undefined::b)) s

data Mult = Mult
instance HMult a b c = Apply Mult (HCons a (HCons b s)) (HCons c s) where
	apply _ (HCons _ (HCons _ s)) = HCons (hadd (undefined::a) (undefined::b)) s

data a @ b = a @ b
instance (Apply a s s',Apply b s' s'') = Apply (a @ b) s'' where
	apply (O a b) s = apply b (apply a s :: s')

type Square = Dup @ Mult
type Cube = Dup @ Dup @ Mult

data I = I
instance Apply a s s' = Apply I (HCons a s) s' where
	apply _ (HCons a s) = apply a s

data Times = Times
instance Apply Times (HCons p (HCons HZero s)) s where
	apply _ (HCons _ s) = s
instance Apply p s s' = Apply Times (HCons p (HCons (HSucc n) s) (HCons p (HCons n s')) where
	apply _ (HCons p (HCons _ s)) = HCons p (HCons (undefined::n) (apply p s))

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-09 Thread Greg Buchholz
Keean Schupke wrote:
 Haskell is not dependantly typed, so cannot deal with types that depend on
 values.

Can anyone recommend a nice dependently typed language to play with?
Cayenne, Epigram, other?


Greg Buchholz

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-09 Thread Peter G. Hancock

 Greg Buchholz wrote (on Wed, 09 Mar 2005 at 20:08):

 Can anyone recommend a nice dependently typed language to play with?
 Cayenne, Epigram, other?

http://www.cs.chalmers.se/~catarina/agda/

See also the sexy IDE alfa: http://www.cs.chalmers.se/~hallgren/Alfa/

Peter Hancock


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-09 Thread Keean Schupke
Greg Buchholz wrote:
Keean Schupke wrote:
 

Haskell is not dependantly typed, so cannot deal with types that depend on
values.
   

   Can anyone recommend a nice dependently typed language to play with?
Cayenne, Epigram, other?
I have refactored your code into a type level Haskell program.
This has the nice advantage that it is extensible. You can add a new
primitive to the language as:
data PrimName
primName :: PrimName
primName = undefined
instance Apply PrimName a b where
   apply _ a = {- method implementing primName -}
Programs are assembled as types like:
   fac4 = lit nul `o` lit suc `o` lit (dup `o` pre)
   `o` lit mult `o` linrec
Recursion requires a primitive to aviod infinite types, see
definitions of times, linrec and genrec.
programs are run by applying the contructed type representing the
program to a stack... for example:
   putStrLn $ show $ apply (lit hThree `o` fac4) hNil
We could have written this:
   putStrLn $ show $ apply fac4 (hCons hThree hNil)
I have attached the debugged code, simply load into ghci, in the same
directory as the HList library (download http://www.cwi.nl/~ralf/HList)
as Joy.hs.
   ghci -fallow-overlapping-instances Joy.hs
(you need the flag to get the code to run interactively, however you
dont need the flag just to run 'main' to perform the factorial tests)
Keean.
  
  

{-# OPTIONS -fglasgow-exts #-}
{-# OPTIONS -fallow-overlapping-instances #-}
{-# OPTIONS -fallow-undecidable-instances #-}

module Joy where

import MainGhcGeneric1

type HOne = HSucc HZero
hOne :: HOne
hOne = undefined
type HTwo = HSucc HOne
hTwo :: HTwo
hTwo = undefined
type HThree = HSucc HTwo
hThree :: HThree
hThree = undefined

data Lit a
lit :: a - Lit a
lit = undefined
unl :: Lit a - a
unl = undefined
instance HList s = Apply (Lit a) s (HCons a s) where
	apply a s = hCons (unl a) s

class (HBool b,HList s) = HIfte b t f s s' | b t f s - s' where
	hIfte :: b - t - f - s - s'
instance (HList s,Apply t s s') = HIfte HTrue t f s s' where
	hIfte _ t _ s = apply t s
instance (HList s,Apply f s s') = HIfte HFalse t f s s' where
	hIfte _ _ f s = apply f s

data Ifte
ifte :: Ifte
ifte = undefined
instance (Apply b s r,HHead r b',HIfte b' t f s s')
	= Apply Ifte (HCons f (HCons t (HCons b s))) s' where
	apply _ (HCons f (HCons t (HCons b s))) = hIfte (hHead (apply b s :: r) :: b') t f s

data Nul
nul :: Nul
nul = undefined
instance HList s = Apply Nul (HCons HZero s) (HCons HTrue s) where
	apply _ (HCons _ s) = hCons hTrue s
instance HList s = Apply Nul (HCons (HSucc n) s) (HCons HFalse s) where
	apply _ (HCons _ s) = hCons hFalse s

data EQ
eq :: EQ
eq = undefined
instance (HList s,TypeEq a b t) = Apply EQ (HCons a (HCons b s)) (HCons t s) where
	apply _ (HCons a (HCons b s)) = hCons (typeEq a b) s

data Dip
dip :: Dip
dip = undefined
instance (HList s,HList s',Apply a s s') = Apply Dip (HCons a (HCons b s)) (HCons b s') where
	apply _ (HCons a (HCons b s)) = hCons b (apply a s)

data Dup
dup :: Dup
dup = undefined
instance HList s = Apply Dup (HCons a s) (HCons a (HCons a s)) where
	apply _ s@(HCons a _) = hCons a s

data Pop
pop :: Pop
pop = undefined
instance HList s = Apply Pop (HCons a s) s where
	apply _ (HCons _ s) = s

data Swap
swap :: Swap
swap = undefined
instance HList s = Apply Swap (HCons a (HCons b s)) (HCons b (HCons a s)) where
	apply _ (HCons a (HCons b s)) = hCons b (hCons a s)

data Suc
suc :: Suc
suc = undefined
instance (HNat a,HList s) = Apply Suc (HCons a s) (HCons (HSucc a) s) where
	apply _ (HCons _ s) = hCons (undefined::HSucc a) s

data Pre
pre :: Pre
pre = undefined
instance (HNat a,HList s) = Apply Pre (HCons (HSucc a) s) (HCons a s) where
	apply _ (HCons _ s) = hCons (undefined::a) s

data Add
add :: Add
add = undefined
instance (HList s,HAdd a b c) = Apply Add (HCons a (HCons b s)) (HCons c s) where
	apply _ (HCons _ (HCons _ s)) = hCons (hAdd (undefined::a) (undefined::b)) s

class (HNat a,HNat b) = HAdd a b c | a b - c where
	hAdd :: a - b - c
instance HAdd HZero HZero HZero where
	hAdd _ _ = hZero
instance HNat b = HAdd HZero (HSucc b) (HSucc b) where
	hAdd _ b = b
instance HNat a = HAdd (HSucc a) HZero (HSucc a) where
	hAdd a _ = a
instance (HNat (HSucc a),HNat (HSucc b),HNat c,HAdd a b c)
	= HAdd (HSucc a) (HSucc b) (HSucc (HSucc c)) where
	hAdd _ _ = hSucc $ hSucc $ hAdd (undefined::a) (undefined::b)

data Sub
sub :: Sub
sub = undefined
instance (HList s,HSub a b c) = Apply Sub (HCons b (HCons a s)) (HCons c s) where
	apply _ (HCons _ (HCons _ s)) = hCons (hSub (undefined::a) (undefined::b)) s

class (HNat a,HNat b) = HSub a b c | a b - c where
	hSub :: a - b - c
instance HSub HZero HZero HZero where
	hSub _ _ = hZero
instance HNat a = HSub (HSucc a) HZero (HSucc a) where
	hSub a _ = a
instance HNat a = HSub HZero (HSucc a) HZero where
	hSub _ _ = hZero
instance (HSub a b c) = HSub (HSucc a) (HSucc b) c where
	hSub _ _ = hSub (undefined::a) (undefined::b)
	
data Mult
mult :: Mult
mult = undefined
instance (HList s,HMult a b c) = Apply Mult (HCons a (HCons 

Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-09 Thread Greg Buchholz
Keean Schupke wrote:
 I have refactored your code into a type level Haskell program.
 This has the nice advantage that it is extensible.

Wow.  Color me impressed.  A little under a week ago, I stumbled
onto Joy, and thought to myself that it could be translated almost
directly into Haskell (which would imply it was possible to statically
type).  Well, it wasn't quite as direct as I had initially thought, but
it looks like you've done it.  Are there any papers/books out there
which I could study to learn more about these (and other) tricks of the
type system wizards? 


Thanks,

Greg Buchholz

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-08 Thread Daniel Fischer
Keean Schupke wrote:
 Daniel Fischer wrote:
 And, BTW, that's why Keean et al's HList library doesn't help here either,
  the type of an HList determines the number of elements and the type of
  each, so there we face the same problems as with nested tuples. What we
  need is type Stack = [ArbitraryType] (from the HList paper, I surmise
  that [Dynamic] would be possible, but that seems to have it's own
  problems).

 Well it depends on what you want to do... If the types of elements are
 determined by the computation then you can use an HList as is, and there
 is no problem.

The problem is that for the recursion combinators we need polymorphic 
recursion functions.
For fact3 we need 
rec2 :: forall l. (HCons a (HCons a l) - HCons a l),
which is illegal in an HList (at least, I haven't found a way to make it 
acceptable) and in tuples.
For the general recursion combinator it's even worse, because 
rec2 may take n2 elements of certain types from the stack, does something with 
them and put k2 elements of certain types determined by the types of the 
consumed elements on the stack, leaving the remainder of the stack unchanged,
rec1 takes n1 elements etc. And the numbers n2, n1 . . . and the types depend 
on the supplied recursion functions.
So (reverting to nested pairs notation), we would have to make linrec to 
accept arguments for rec2 of the types
(a,b) - (r,b),
(a,(a1,b)) - (r,(r1,(r2,b))),
(a,(a1,b)) - (r,b)
(a,(a1,(a2,b))) - (r,b)

and so on, for arbitrary munch- and return-numbers, where we don't care what b 
is. These can't be unified however, so I think it's impossible to transfer 
these combinators faithfully to a strongly typed language. [Dynamic] won't 
work either, I believe, because Dynamic objects must be monomorphic, as I've 
just read in the doc.

The point is, in Joy all these functions would have type Stack - Stack and we 
can't make a stack of four elements the same type as a stack of six elements 
using either nested pairs or HLists (correct me if I'm wrong, you know HList 
better than I do).

However, Joy has only very few datatypes (according to the introduction I 
looked at), so

data Elem = Bool Bool
 | Char Char
 | Int Integer
 | Double Double
 | String String
 | Fun (Stack - Stack)
 | List [Elem]
 | Set [Int]

type Stack = [Elem]

type Joy = State Stack (IO ())

looks implementable, probably a lot to write, but not too difficult - maybe, 
I'll try.


 The only time there is a problem is if the _type_ of an element to be put
 in an HList depends on an IO action. In this case you need to existentially
 quantify the HList.

How would I do that?
What the user's guide says about existential quantification isn't enough for 
me.

 So you can use the HList in both cases, but you have to deal with
 existential
 types if the type of the HList is dependant on IO (you dont have to do this
 if only the value of an element depends on IO).

 Keean.

If you can faithfully implement Greg's code (including fact3-5) using HList, 
I'd be interested to see it, I think HList suits other purposes far better.

Daniel

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-08 Thread Daniel Fischer
Am Dienstag, 8. März 2005 17:31 schrieben Sie:
 Daniel Fischer wrote:
 The problem is that for the recursion combinators we need polymorphic
 recursion functions.
 For fact3 we need
 rec2 :: forall l. (HCons a (HCons a l) - HCons a l),

 I dont see why this is illegal... what do we want? take the top two
 items from the stack?

It's illegal, because a type variable may not be instantiated by a 
forall-type; section 7.4.9 of the user's guide:
There is one place you cannot put a forall: you cannot instantiate a type 
variable with a forall-type. So you cannot make a forall-type the argument of 
a type constructor. So these types are illegal: 

   x1 :: [forall a. a-a]
x2 :: (forall a. a-a, Int)
x3 :: Maybe (forall a. a-a).

I'd say that also applys to HList,
HCons (forall l. (HCons a (HCons a l) - HCons a l)) blah
won't work (and my ghci doesn't swallow it).

 Take the to N elements from the stack:

 class Take l n h t | l n - h t where
 take :: l - n - (h,t)
 instance Take l HZero HNil l where
 take l _ = (HNil,l)
 instance Take t n (h',t') = Take (HCons h t) (HSucc n) (HCons h h',t')
 where
 take (HCons h t) (_::HSucc n) = (HCons h h',t')
where (h',t') = take t (undefined::n)

Good, but cumbersome. And I'm not sure what the type signature should be for

genrec (HCons rec2 (HCons rec1 (HCons t (HCons b stack
| hHead (b stack) = t stack
| otherwise = rec2 (HCons (genrec.quote rec2.quote rec1.quote t.quote b)
 (rec1 stack))

I dare say it would be easier in Haskell-style:

genrec rec2 rec1 t b stack.

 For the general recursion combinator it's even worse, because
 rec2 may take n2 elements of certain types from the stack, does something
  with them and put k2 elements of certain types determined by the types of
  the consumed elements on the stack, leaving the remainder of the stack
  unchanged, rec1 takes n1 elements etc. And the numbers n2, n1 . . . and
  the types depend on the supplied recursion functions.
 So (reverting to nested pairs notation), we would have to make linrec to
 accept arguments for rec2 of the types
 (a,b) - (r,b),
 (a,(a1,b)) - (r,(r1,(r2,b))),
 (a,(a1,b)) - (r,b)
 (a,(a1,(a2,b))) - (r,b)
 
 and so on, for arbitrary munch- and return-numbers, where we don't care
  what b is. These can't be unified however, so I think it's impossible to
  transfer these combinators faithfully to a strongly typed language.
  [Dynamic] won't work either, I believe, because Dynamic objects must be
  monomorphic, as I've just read in the doc.
 
 The point is, in Joy all these functions would have type Stack - Stack
  and we can't make a stack of four elements the same type as a stack of
  six elements using either nested pairs or HLists (correct me if I'm
  wrong, you know HList better than I do).

 They are not the same type, but that are the same Kind, or Type-Familly...

Aye, but as I understand it, once we push the recursion functions on the 
stack, they must be monomorphic, which means, the scheme won't work in 
general. 

 class Stack s
 instance Stack HNil
 instance Stack s = Stack (HCons a s)

Isn't this exactly the HList class?

 isItAStack :: Stack s = s - s
 isItAStack = id

 However, Joy has only very few datatypes (according to the introduction I
 looked at), so
 
 data Elem = Bool Bool
 
  | Char Char
  | Int Integer
  | Double Double
  | String String
  | Fun (Stack - Stack)
  | List [Elem]
  | Set [Int]
 
 type Stack = [Elem]
 
 type Joy = State Stack (IO ())
 
 looks implementable, probably a lot to write, but not too difficult -
  maybe, I'll try.

 The above can be translated to HLists, the difference is that with
 HLists the types (classes)
 are extensible.

Might well be, only I don't see how (would have to take a log look at 
HList, probably).
Of course, doing it the primitive way means a lot of work every time you add a 
new datatype :-(
But for these types, I did it (with a few modifications) and all works fine.

 There appears to be no IO in the example Joy code so existentials are
 unneccessary.

No IO around, I only thought I might wish to write an interactive frontend, 
printing out the top of the stack (might be an error message) after each 
step. I haven't got round to that yet, and I don't know whether I will, but I 
think if I do, I'd better use type Joy = IO (State Stack Elem).

 Keean.

Daniel

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-08 Thread Greg Buchholz
Keean Schupke wrote:
 I dont see why this is illegal... what do we want? take the top two 
 items from the stack?

With the code below (direct translation from tuples to HLists) I
still get an occurs check error when trying to define fact5...


Compiling Main ( joy3.hs, interpreted )

joy3.hs:23:
Occurs check: cannot construct the infinite type: l = HCons e l
Expected type: HCons
   (HCons e (HCons e l) - HCons e l)
   (HCons
(HCons e3 l3 - HCons e3 (HCons e3 l3))
(HCons
 (HCons e1 l2 - HCons e1 l2)
 (HCons (HCons e2 l1 - HCons Bool l1) a)))
   - c
Inferred type: HCons
   (HCons e (HCons e l) - HCons e (HCons e l))
   (HCons
(l4 - l4)
(HCons (l4 - HCons e (HCons e l))
(HCons (l4 - l5) l4)))
   - HCons e (HCons e l)
In the second argument of `(!)', namely `linrec'
In the definition of `fact5':
fact5 = quote (nul)) ! (quote (suc))) ! (quote (dup ! pre)))
 ! (quote (mult)))
! linrec
Failed, modules loaded: MainGhcGeneric1, TypeCastGeneric1, Label3,
TypeEqGeneric1, TypeEqBoolGeneric, GhcExperiments, GhcSyntax,
CommonMain, Datatypes2, Variant, TIC, TIP, HTypeIndexed, GhcRecord,
Record, HZip, HOccurs, HArray, HListPrelude, FakePrelude.


Looks to me like a very similar error to the tuple case.

Greg Buchholz



--Joy combinators in Haskell
{-# OPTIONS -fglasgow-exts #-}
{-# OPTIONS -fallow-overlapping-instances #-}

import MainGhcGeneric1
import Data.Typeable

main = do   print $ ((lit 10)!(lit 4)!mult) bot  -- 4*10
print $ ((lit 3) ! cube ) bot-- 3^3
print $ ((lit 4) ! fact5) bot-- 4!

bot = HNil
square = dup ! mult
cube   = dup ! dup ! mult ! mult
nul = (lit 0) ! eq
suc = (lit 1) ! add
pre = (lit 1) ! sub


--In Joy:  [null]  [succ]  [dup pred]  [*]  linrec
fact5 :: HCons Integer a - HCons Integer a
fact5 = quote(nul) ! quote(suc) ! quote(dup ! pre) ! quote(mult) ! linrec
--}

--primitive combinators
(!) f g = g.f
i(a, b)  = (a b)
add  (HCons a (HCons b c)) = (HCons (b+a) c)
sub  (HCons a (HCons b c)) = (HCons (b-a) c)
mult (HCons a (HCons b c)) = (HCons (b*a) c)
swap (HCons a (HCons b c)) = (HCons b (HCons a c))
pop  (HCons a b)   =  b
dup  (HCons a b)   = (HCons a (HCons a b)) 
dip  (HCons a (HCons b c)) = (HCons b, (a  c)) 
eq   (HCons a (HCons b c)) | a == b= (HCons True c)
   | otherwise = (HCons False c)

ifte (HCons f (HCons t (HCons b stack))) 
  | hHead(b stack) = (t stack)
  | otherwise  = (f stack)

linrec (HCons rec2 (HCons rec1 (HCons t (HCons p stack
  | hHead (p stack) = (t stack)
  | otherwise   = rec2 (linrec (HCons rec2 
   (HCons rec1 
   (HCons t 
   (HCons p (rec1 stack))

lit val stack = (HCons val stack)
quote = lit


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-07 Thread Greg Buchholz
Daniel Fischer wrote:
 Am Freitag, 4. M?rz 2005 19:35 schrieb Greg Buchholz:
  So, can anyone direct me towards more information on exactly
  what an Occurs check is, or does anyone see an easy fix to my
  problems?
 
 If I remember correctly, an occurs check is checking whether a type 
 variable 
 (call it 't') occurs as an argument to a tuple constructor or function arrow 
 in a type expression to be substituted for t, as above or in 
 t = t - t1.
 
 Such occurences would lead to an infinite type, hence are forbidden.

   Interesting, I'll have to think it over. (Of course being a relative
newcomer to Haskell, I have to do a lot of thinking when it comes to
most things.)  BTW, can anyone recommend a good introductory resource
for learning about type theory?  I once flipped through Pierce's
Types_and_Programming_Languages, but at first glance, it seemed to be a
little advanced for my understanding (the foreign-looking equations per
word ratio seemed a little too high).

 I have a fix for the factorial and similar recursive functions, though it's 
 not really easy (and needs extensions):
 don't define the recursion combinators via Stack, do it like this:
 
 linrec2 :: forall a. (forall b. (a,(a,b)) - (a,b)) -
  (forall b. (a,b) - (a,(a,b))) -
(forall b. (a,b) - (a,b)) -
(forall b. (a,b) - (Bool,b)) -
(forall b. (a,b) - (a,b))
 linrec2 rec2 rec1 t p stack
| fst $ p stack = t stack
| otherwise = rec2 $ linrec2 rec2 rec1 t p (rec1 stack)

Nice.  Definitely something for me to study.  Of course, IFAICT, the
main motivation for Joy is to try and define everything in terms of
function composition instead of function application.

 I don't know Joy, but probably there the stack is (roughly) a heterogenous 
 list, which is hard to model in Haskell,

Yeah, I don't know Joy either, other than reading a few documents,
but I do think its stack is really heterogenous list.  The one reason I
was thinking this might be doable in Haskell, is the fact that the few
combinators I looked at don't recurse down the whole stack.  That, of
course, would be a complete nightmare in Haskell.   Instead they take a
stack, munge a few (finite number of) items at the top, and return
another stack.  I was hoping that the type variable a in (Integer,
a) - (Integer, a) would be amorphous enough to match whatever was left
over after grabbing a few items off the top of this stack.

Thanks,

Greg Buchholz

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-07 Thread Daniel Fischer
Am Montag, 7. März 2005 17:58 schrieb Greg Buchholz:
 Daniel Fischer wrote:
  Am Freitag, 4. März 2005 19:35 schrieb Greg Buchholz:
   So, can anyone direct me towards more information on exactly
   what an Occurs check is, or does anyone see an easy fix to my
   problems?
 
  If I remember correctly, an occurs check is checking whether a type
  variable (call it 't') occurs as an argument to a tuple constructor or
  function arrow in a type expression to be substituted for t, as above or
  in
  t = t - t1.
 
  Such occurences would lead to an infinite type, hence are forbidden.

Interesting, I'll have to think it over. (Of course being a relative
 newcomer to Haskell, I have to do a lot of thinking when it comes to
 most things.)  BTW, can anyone recommend a good introductory resource
 for learning about type theory?  I once flipped through Pierce's
 Types_and_Programming_Languages, but at first glance, it seemed to be a
 little advanced for my understanding (the foreign-looking equations per
 word ratio seemed a little too high).

  I have a fix for the factorial and similar recursive functions, though
  it's not really easy (and needs extensions):
  don't define the recursion combinators via Stack, do it like this:
 
  linrec2 :: forall a. (forall b. (a,(a,b)) - (a,b)) -
   (forall b. (a,b) - (a,(a,b))) -
   (forall b. (a,b) - (a,b)) -
   (forall b. (a,b) - (Bool,b)) -
   (forall b. (a,b) - (a,b))
  linrec2 rec2 rec1 t p stack
 
 | fst $ p stack = t stack
 | otherwise = rec2 $ linrec2 rec2 rec1 t p (rec1 stack)

 Nice.  Definitely something for me to study.  Of course, IFAICT, the
 main motivation for Joy is to try and define everything in terms of
 function composition instead of function application.

One more, you need not supply a type signature for fact, if you provide the 
argument:

fact0 (n,st) = ifte (dup ! pre ! fact ! mult, (pop ! lit 1, (nul, (n,st

That's of course rather unJoyful :-), but it helps the type-checker (I don't 
know the workings thereof, but it's often the case that functions which don't 
type-check points-free do if sufficiently many arguments are provided).

I don't think that'll help fact3-5, though.


  I don't know Joy, but probably there the stack is (roughly) a
  heterogenous list, which is hard to model in Haskell,

 Yeah, I don't know Joy either, other than reading a few documents,

I've taken a look, and I must say, I find Haskell more intuitive.

 but I do think its stack is really heterogenous list.  The one reason I
 was thinking this might be doable in Haskell, is the fact that the few
 combinators I looked at don't recurse down the whole stack.  That, of

I think, it would be possible to define recursion combinators for specific 
patterns, like this functions takes 4 elements from the stack, this one 3 and 
so on, but then you would need combinators for all these patterns, which is 
rather cumbersome.

IMO, it's just not the thing to do things in Haskell exactly like in Joy (or 
in Java, prolog, or - horribile dictu- in C/C++). Even if it's possible, the 
spirit of the languages is so different that you should do the same thing in 
different ways. But of course it's interesting to see whether it can be done.

 course, would be a complete nightmare in Haskell.   Instead they take a
 stack, munge a few (finite number of) items at the top, and return

That's nightmarish enough, because Haskell is strongly typed.
So, if we look at linrec, for example, we find that rec2 and rec1 must return 
the same type as they devour, that's why fact5 doesn't work, because
mult has type 
Num a = (a,(a,b)) - (a,b).

And, BTW, that's why Keean et al's HList library doesn't help here either, the 
type of an HList determines the number of elements and the type of each, so 
there we face the same problems as with nested tuples. What we need is 
type Stack = [ArbitraryType] (from the HList paper, I surmise that [Dynamic] 
would be possilble, but that seems to have it's own problems).

 another stack.  I was hoping that the type variable a in (Integer,
 a) - (Integer, a) would be amorphous enough to match whatever was left
 over after grabbing a few items off the top of this stack.

Well, it's fairly amorphous, but it must be the same type in both 
type-expressions, and that's why the points-free definition of fact doesn't 
type-check without the type signature, the 'fact' in the else-branch is used 
at type (Integer,(Integer,a)) and so on, without the type signature, the 
type-checker assumes that it must be instantiated at exactly the same type, 
which it isn't. With the signature, the type-checker knows that 'fact' is 
polymorphic and that it's perfectly all right to instantiate it at a 
different type in the recursive call. 

Well, at least that's what I worked out from my sparse knowledge, if I'm 
wrong, would somebody please correct me?


 Thanks,

 Greg Buchholz

HTH,
Daniel

Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-07 Thread Keean Schupke
Daniel Fischer wrote:
And, BTW, that's why Keean et al's HList library doesn't help here either, the 
type of an HList determines the number of elements and the type of each, so 
there we face the same problems as with nested tuples. What we need is 
type Stack = [ArbitraryType] (from the HList paper, I surmise that [Dynamic] 
would be possilble, but that seems to have it's own problems).

 

Well it depends on what you want to do... If the types of elements are
determined by the computation then you can use an HList as is, and there
is no problem.
The only time there is a problem is if the _type_ of an element to be put
in an HList depends on an IO action. In this case you need to existentially
quanify the HList.
So you can use the HList in both cases, but you have to deal with 
existential
types if the type of the HList is dependant on IO (you dont have to do this
if only the value of an element depends on IO).

   Keean.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-07 Thread Greg Buchholz
Daniel Fischer wrote:
 I think, it would be possible to define recursion combinators for specific 
 patterns, like this functions takes 4 elements from the stack, this one 3 and 
 so on, but then you would need combinators for all these patterns, which is 
 rather cumbersome.

Hmm.  The standard Joy combinators probably can't be typed, so maybe
my next step would be to find/create a recursion combinator with a
static type.  Surely one must exist? If you can have a typed lambda
calculus, you must be able to have a typed SK combinator calculus,
right? (Now I'm way out of my league.)  I'll have to think some more on
why you couldn't have a recursion combinator which was more generic than
the one that takes 3 items off the stack, or 4 items, rather than n
items.  Or maybe the whole idea of using a stack is the essential
weakness.

 
 IMO, it's just not the thing to do things in Haskell exactly like in Joy (or 
 in Java, prolog, or - horribile dictu- in C/C++). Even if it's possible, the 
 spirit of the languages is so different that you should do the same thing in 
 different ways. But of course it's interesting to see whether it can be done.

Yeah.  I'm only in it for the brain exercise, not to convert the
masses over to Joy ;-)

  ...another stack.  I was hoping that the type variable a in (Integer,
  a) - (Integer, a) would be amorphous enough to match whatever was left
  over after grabbing a few items off the top of this stack.
 
 Well, it's fairly amorphous, but it must be the same type in both 
 type-expressions, and that's why the points-free definition of fact doesn't 
 type-check without the type signature, the 'fact' in the else-branch is used 
 at type (Integer,(Integer,a)) and so on, without the type signature, the 
 type-checker assumes that it must be instantiated at exactly the same type, 
 which it isn't. With the signature, the type-checker knows that 'fact' is 
 polymorphic and that it's perfectly all right to instantiate it at a 
 different type in the recursive call. 

That pretty much sums up why I thought the whole crazy scheme might
work, only in better words.


Greg Buchholz

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-07 Thread John Meacham
On Mon, Mar 07, 2005 at 08:47:11PM +0100, Daniel Fischer wrote:
 And, BTW, that's why Keean et al's HList library doesn't help here either, 
 the 
 type of an HList determines the number of elements and the type of each, so 
 there we face the same problems as with nested tuples. What we need is 
 type Stack = [ArbitraryType] (from the HList paper, I surmise that [Dynamic] 
 would be possilble, but that seems to have it's own problems).

It would be interesting if you could use the HList framework for
'partially typed lists' in that if your stack is an hlist, an operation
like plus would be
plus :: forall a. HList a = Int :*: Int :*: a - Int :*: a

which says that plus goes from ANY Hlist starting with two ints and
returns that hlist with a single Int on it. basically you use a
universally quantified type to represent the unknown tail of the list
(everything else on the stack).

not sure if it works.. just brainstorming It seems very natural if
it could be made to work.

John



-- 
John Meacham - repetae.netjohn 
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-06 Thread Keean Schupke
Daniel Fischer wrote:
I don't know Joy, but probably there the stack is (roughly) a heterogenous 
list, which is hard to model in Haskell, think of

data Element = Bool Bool
 | Char Char
 | Int Int
  . . .
 | IntToBool (Int - Bool)
  . . .
type Stack = [Element]
and how to define functions for that, urgh.
 

Not saying it isn't tricky - but thats what the HList library 
(http://www.cwi.nl/~ralf/HList) implements, a heterogenous list.
It works slightly differently using classes, but does abstract the
workings enough to be useful, to construct an HList you can do:

hlist = a .*. (3:Int) .*. False .*. 'v' .*. HNil
And provides head/tail functions and other useful list and set
operators.
   Keean.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-06 Thread Daniel Fischer
Keean wrote:

 Not saying it isn't tricky - but thats what the HList library
 (http://www.cwi.nl/~ralf/HList) implements, a heterogenous list.
 It works slightly differently using classes, but does abstract the
 workings enough to be useful, to construct an HList you can do:

 hlist = a .*. (3:Int) .*. False .*. 'v' .*. HNil

 And provides head/tail functions and other useful list and set
 operators.

 Keean.

Phew, not bad, but not easy to absorb. 

Do you know whether the Joy Combinators would work with HList?
If I find the time, I'll try to see for myself tomorrow, but I'm not sure that 
I will.

Respectfully,
Daniel
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-05 Thread Daniel Fischer
Am Freitag, 4. März 2005 19:35 schrieb Greg Buchholz:
 Recently, while investigating the (non-statically typed) stack-based
 functional language Joy
 (http://www.latrobe.edu.au/philosophy/phimvt/joy.html), I became interested
 in seeing if I could implement Joy's combinators in Haskell.  I started
 with a stack based implementation using nested tuples as the stack.  Things
 worked out well until I got to the
 recursion combinators.  Even then, things didn't seem that bad, since
 Haskell was able to infer types for the the linrec and genrec
 combinators.  Trouble popped up when I tried to apply the recursion
 operators to a function (in this case calculating the humble factorial).
 In the code below, fact3,4  5 all fail with an Occurs check that
 looks something like the following...

 joy3.hs:24:
 Occurs check: cannot construct the infinite type: t = (a, t)
 Expected type: ((a5 - (a, (a, t)), a5) - (a, t),
 ((a1, t3) - (a1, (a1, t3)),
  ((a2, t2) - (a2, t2), ((a3, t1) - (Bool,
 t1),a4 - c
 Inferred type: ((a5 - (a, (a, t)), a5) - (a, (a, t)),
 (a5 - a5, (a5 - (a, (a, t)), (a5 - (Bool,
 b),a5 - (a, (a, t))

 ...Normally, I would have given up and declared that Joy wasn't an easily
 typed language, but I'm motivated to dig further because if you remove
 the type signature from fact below, it also fails with an Occurs
 check.  So, can anyone direct me towards more information on exactly
 what an Occurs check is, or does anyone see an easy fix to my
 problems?

If I remember correctly, an occurs check is checking whether a type variable 
(call it 't') occurs as an argument to a tuple constructor or function arrow 
in a type expression to be substituted for t, as above or in 
t = t - t1.

Such occurences would lead to an infinite type, hence are forbidden.
If you really think you need such things, 

data Pair a b = P (a, (Pair a b))

works, however that type contains no fully defined values, so is only of 
limited usefulness.

I have a fix for the factorial and similar recursive functions, though it's 
not really easy (and needs extensions):
don't define the recursion combinators via Stack, do it like this:

linrec2 :: forall a. (forall b. (a,(a,b)) - (a,b)) -
 (forall b. (a,b) - (a,(a,b))) -
 (forall b. (a,b) - (a,b)) -
 (forall b. (a,b) - (Bool,b)) -
 (forall b. (a,b) - (a,b))
linrec2 rec2 rec1 t p stack
   | fst $ p stack = t stack
   | otherwise = rec2 $ linrec2 rec2 rec1 t p (rec1 stack)

and similarly for genrec. Then you can define

fact6 = linrec2 mult (dup ! pre) suc nul.

You cannot use linrec, because rec2 and rec1 must each have identical result 
and argument types:
*Joy :t linrec
linrec :: forall t b b.
  (t - t, (b - b, (b - t, (b - (Bool, b), b - t

I don't know Joy, but probably there the stack is (roughly) a heterogenous 
list, which is hard to model in Haskell, think of

data Element = Bool Bool
  | Char Char
  | Int Int
   . . .
  | IntToBool (Int - Bool)
   . . .

type Stack = [Element]

and how to define functions for that, urgh.


 Thanks,

 Greg Buchholz

 P.S. The first thing you should note about the code below is the
 definition of the reverse composition operator (!), which I used to give
 the program a more Joy-like feel. (i.e. (!) f g = g.f)

 --Joy combinators in Haskell
 
 main = do   print $ ((lit 6) ! fact) bot-- factorial of 6
 print $ ((lit 2) ! square ! fact2) bot  -- factorial of 4
 
 bot = EOS -- end of stack
 square = dup ! mult
 cube = dup ! dup ! mult ! mult
 
 --In Joy: factorial == [0 =] [pop 1] [dup 1 - factorial *] ifte
 fact :: (Integer, a) - (Integer, a)
 fact =  (quote ((lit 0) ! eq)) !
 (quote (pop ! (lit 1))) !
 (quote (dup ! (lit 1) ! sub ! fact ! mult)) !
 ifte
 
 --In Joy: [1 1] dip [dup [*] dip succ] times pop
 fact2 = (quote ((lit 1) ! (lit 1)))
 ! dip ! (quote (dup ! (quote mult) ! dip ! suc))
 ! times ! pop
 
 {- fact3,4  5 don't type check, fails with...
 -- Occurs check: cannot construct the infinite type:
 
 --In Joy: [null] [succ] [dup pred] [i *] genrec
 fact3 :: (Integer, a) - (Integer, a)
 fact3 = (quote nul) ! (quote suc) ! (quote (dup ! pre)) ! (quote (i !
  mult)) ! genrec
 
 fact4 :: (Integer, a) - (Integer, a)
 fact4 = genrec.quote(mult.i).quote(pre.dup).quote(suc).quote(nul)
 
 --In Joy:  [null]  [succ]  [dup pred]  [*]  linrec
 fact5 :: (Integer, a) - (Integer, a)
 fact5 = quote(nul) ! quote(suc) ! quote(dup ! pre) ! quote(mult) ! linrec
 
 --}
 nul = (lit 0) ! eq
 suc = (lit 1) ! add
 pre = (lit 1) ! sub
 
 linrec (rec2, (rec1, (t, (p, stack
 
   | fst (p stack) == True = (t stack)
 ^^
 fst (p stack) suffices.

   | otherwise = 

[Haskell-cafe] Joy Combinators (Occurs check: infinite type)

2005-03-04 Thread Greg Buchholz

Recently, while investigating the (non-statically typed) stack-based
functional language Joy (http://www.latrobe.edu.au/philosophy/phimvt/joy.html),
I became interested in seeing if I could implement Joy's combinators in 
Haskell.  I started with a stack based implementation using nested
tuples as the stack.  Things worked out well until I got to the
recursion combinators.  Even then, things didn't seem that bad, since
Haskell was able to infer types for the the linrec and genrec
combinators.  Trouble popped up when I tried to apply the recursion
operators to a function (in this case calculating the humble factorial).
In the code below, fact3,4  5 all fail with an Occurs check that
looks something like the following...

joy3.hs:24:
Occurs check: cannot construct the infinite type: t = (a, t)
Expected type: ((a5 - (a, (a, t)), a5) - (a, t),
((a1, t3) - (a1, (a1, t3)),
 ((a2, t2) - (a2, t2), ((a3, t1) - (Bool, t1),a4
   - c
Inferred type: ((a5 - (a, (a, t)), a5) - (a, (a, t)),
(a5 - a5, (a5 - (a, (a, t)), (a5 - (Bool, b),a5
   - (a, (a, t))

...Normally, I would have given up and declared that Joy wasn't an easily
typed language, but I'm motivated to dig further because if you remove
the type signature from fact below, it also fails with an Occurs
check.  So, can anyone direct me towards more information on exactly
what an Occurs check is, or does anyone see an easy fix to my
problems?


Thanks,

Greg Buchholz 

P.S. The first thing you should note about the code below is the
definition of the reverse composition operator (!), which I used to give
the program a more Joy-like feel. (i.e. (!) f g = g.f)

--Joy combinators in Haskell

main = do   print $ ((lit 6) ! fact) bot-- factorial of 6
print $ ((lit 2) ! square ! fact2) bot  -- factorial of 4

bot = EOS -- end of stack
square = dup ! mult
cube = dup ! dup ! mult ! mult

--In Joy: factorial == [0 =] [pop 1] [dup 1 - factorial *] ifte
fact :: (Integer, a) - (Integer, a)
fact =  (quote ((lit 0) ! eq)) !
(quote (pop ! (lit 1))) !
(quote (dup ! (lit 1) ! sub ! fact ! mult)) !
ifte

--In Joy: [1 1] dip [dup [*] dip succ] times pop
fact2 = (quote ((lit 1) ! (lit 1)))
! dip ! (quote (dup ! (quote mult) ! dip ! suc))
! times ! pop

{- fact3,4  5 don't type check, fails with...
-- Occurs check: cannot construct the infinite type:

--In Joy: [null] [succ] [dup pred] [i *] genrec
fact3 :: (Integer, a) - (Integer, a)
fact3 = (quote nul) ! (quote suc) ! (quote (dup ! pre)) ! (quote (i ! mult))
! genrec

fact4 :: (Integer, a) - (Integer, a)
fact4 = genrec.quote(mult.i).quote(pre.dup).quote(suc).quote(nul)

--In Joy:  [null]  [succ]  [dup pred]  [*]  linrec
fact5 :: (Integer, a) - (Integer, a)
fact5 = quote(nul) ! quote(suc) ! quote(dup ! pre) ! quote(mult) ! linrec

--}
nul = (lit 0) ! eq
suc = (lit 1) ! add
pre = (lit 1) ! sub

linrec (rec2, (rec1, (t, (p, stack
  | fst (p stack) == True = (t stack)
  | otherwise = rec2 (linrec (rec2, (rec1, (t, (p, (rec1 stack))

genrec (rec2, (rec1, (t, (b, stack
  | fst (b stack) == True = (t stack)
  | otherwise = (rec2.quote(genrec.quote(rec2).quote(rec1).
  quote(t).quote(b))) (rec1 stack)

times (p, (n, stack)) | n0 = times (p, (n-1, (p stack)))
  | otherwise = stack

(!) f g = g.f
i(a, b)  = (a b)
add  (a, (b, c)) = (b+a, c)
sub  (a, (b, c)) = (b-a, c)
mult (a, (b, c)) = (b*a, c)
swap (a, (b, c)) = (b, (a, c))
pop  (a, b)  =  b
dup  (a, b)  = (a, (a, b))
dip  (a, (b, c)) = (b, (a  c))
eq   (a, (b, c)) | a == b= (True, c)
 | otherwise = (False,c)

ifte (f, (t, (b, stack))) | fst (b stack) == True = (t stack)
  | otherwise = (f stack)

lit val stack  = (val, stack) -- push literals on the stack
quote = lit


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe