codereport / jello

A Python script for wrapping Jellyfish (a fork of Jelly) so you can more easily play with the language.
MIT License
48 stars 4 forks source link

Chain Reductions pattern matching table #36

Open tom-huntington opened 3 months ago

tom-huntington commented 3 months ago

I wrote a table to help you know how to perform reductions on the chains. In a monadic or dyadic chain, reductions always result in an monad or dyad respectively. (Nilads can just be promoted to constant n-ads in an n-adic chain???)

| chain | dyadic | | :------------------------:| :----: | | `2 2 …` |
`2 2 2 …``Φ₁ …`
`2 2 …``ε{",'} …`
| | `2 1 …` | `B₁ …` | | `1 2 …` |
`1 2 2 …``Φ.₂ …`
`1 2 …``Δ …`
| | `1 1 …` | `B.₃ …` |
| chain | monadic | | :------: | :-----: | | `1 2 …` |
`1 2 1 …``Φ …`
`1 2 …``Σ …`
| | `1 1 …` | `B …` | | `2 …` |
`2 1 …``S …`
`2 …``W …`
|
ε" f g = x y -> f(x, g(x,y))
ε' f g = x y -> g(f(x,y), y)
B.₃ f g = x y -> g(f(x)) 

I found some issues with Jello's combinator trees:

ε' issue

The pairs here associate to the right [1, [1, 10]]

> 1 10 :: pair pair
           ,    ,
   ,  1 10 ➡️  [1, 10]
   ,, 1 10 ➡️  [1, [1, 10]]
    This is a 2-2 dyadic chain (ε')
              └┬┘
              ε'

but the pairs here associate to the left [[2, 11], 10]

> 1 10 :: pair add1 pair
           ,    ‘    ,
   ,   1 10 ➡️  [1, 10]
   ,‘  1 10 ➡️  [2, 11]
   ,‘, 1 10 ➡️  [[2, 11], 10]
    This is a 2-1-2 dyadic chain (B₁ε')
              └┬┘ ⋮
              B₁  ⋮
               └┬─┘
               ε'

although 2-1-2 reduces to 2-2 so the only difference is whether the first dyad is a reduction or not.

codereport commented 3 months ago

Thanks for this! Will address all in the future.

I also want to change Jellyfish to work such that the first chain in a multichain has a fixed arity (I think that is what I want at least). Added these spellings recently ⬇️ but when I modified Jellyfish do have better support for D2 I couldn't figure out how to register the first chain of a multichain as monadic when it is called in a dyadic context. If you have thoughts let me know : )

image

tom-huntington commented 3 months ago

@codereport Edit: read my next comment ⬇️

I kind of think your mental model is a bit confused. This is my mental model. explicitly use parentheses ( for a monadic subchains, curly parentheses { for a dyadic subchain.

< . sort rev sums . sum . sum add1
{< (sort rev sums) sum} (sum add1)
{< f1 sum} (sum add1)
2 1
= B₁ if dyadic
= S if monadic

So its not the "first chain" whose arity is context dependant. Only subchains have specified arity. Once all the subchains have been reduced, the resulting chain still depends on the context.


You can get what you want by inserting a chain separator before each function of the same arity. (here add1 is a fill in for the chain of your choice)

 1 10 :: . add1 : pair : pair
           (add1) {pair} {pair}
            1 2 2            
[2, [1, 10]]
> 1 10 :: add1 pair pair
             1 2 2
[2, [1, 10]]

Adding a separator before each function is necessary because:

> 1 10 :: . add1 : pair pair
              (add1) {pair pair}
              1 2       <- !!!! DIFFERENT to 1 2 2
[2, [2, 10]] <- DIFFERENT

So, what you would need to add in jellyfish is another separator (say ;) that ends "subchains", without starting a new subchain.

then with ; you could do

. add1 ; pair pair
(add1) pair pair
1 2 2

Breaking change

Also are you aware that your better support for D2 is a breaking change

Dyadic 2 1 1 use to be B₁B₁ now it is D₂. The original l f₁ : g₂ : r h₁ spelling seemed fine to me

P.S.

My development style is to understand the issues, and then not fix them. So don't feel pressure, to fix them yourself

codereport commented 3 months ago

My mental model is/was definitely wrong. I didn't realize the chain is formed and then the context still matters. I also feel like i don't totally understand explicitly what the delineation of link/subchain/chain is.

How did you learn all of this? Just by trial and error? or looking at the source code?

tom-huntington commented 3 months ago

@codereport I'm trained as a mathematician, it's just the logical way to do these operations. Denis implemented it quite different, more like a stack based language. So my mental model is a bit different to his implementation

codereport commented 3 months ago

Interesting. And yea, I realized that I could have just used a monadic separator to get what I wanted with the d2 combinator. But I like the expressions having a fixed meaning i.e. it can only be called monadically or dyadically. Maybe after I play around with it maybe I wouldn't like it as much though. You might be right that the subchain ender is what I want.

tom-huntington commented 3 months ago

@codereport I agree that you should have to specify the arity at function definition, and throw an error if the wrong number of arguments are passed. However, your d2 change is orthogonal.

I think you got tripped up by the fact that Dennis' implementation is using the fact the the following are equivalent:

f₁ g₂ h₁ k₂ : ...
. f₁ : g₂ . h₁ : k₂ : ...

IMO, It's better to think of jelly working as the second, each atom is implicitly separated until the first separator.

Also my mental model: jelly is a language for writing extremely nested compositions of functions. At the end of the day, it should be implemented by construct a single function then calling it, rather than Dennis' the stack based implementation.