Integrated Dynamics

Integrated Dynamics

63M Downloads

Feature Request: Functions

ricochet1k opened this issue · 6 comments

commented

So, I'm trying to come up with a way to use Integrated Dynamics and Tunnels to make an autocrafting system for Botania. Here's what I've come up with so far, in pseudo-Haskell style:

targetList :: List Item
targetList = <proxy>

currentInv :: List Item
currentInv = <chest inventory>

stillNeed :: List Item
stillNeed = filter (not . haveEnough) targetList

haveEnough :: Item -> Boolean
haveEnough item = gt (size item) . haveAlready item

haveAlready :: Item -> Int
haveAlready = itemCounts . sameItems

itemCounts :: List Item -> Int
itemCounts = reduce (+) . map size

sameItems :: Item -> List Item
sameItems = (flip filter) currentInv . eq

The idea is to have an inventory reader and an item exporter attached to a chest, with an item interface somewhere else. currentInv would be the Inventory Items aspect of the inventory reader, targetList would be a proxy where you can insert the list of items you want placed in the chest, exactly, and no more.

My Haskell is a bit rusty, but I think this would work. Maybe there's a different way to do this, but as far as I can tell, it isn't possible to do the haveEnough part because the item parameter is used twice.

So, my request is this: Let us make functions. Let us make Parameter cards, and then make a function by inserting the Parameter cards and the result card. Parameter cards can be duplicated and then used in multiple places. Also, if the result card refers to a Parameter card that's not included in the function, it should still be able to be used inside another function. Or in other words, don't prevent constructing the function if all the Parameters are not included.

Functions would also be useful to make composing Operators easier. Point-free style is not intuitive for most people.

commented

@ricochet1k The new pipe2 operator will now let you do what you wanted to do. Use it like pipe2 size haveAlready gt. It's the equivalent of Haskell's liftM2, but with its operands in a different order. liftM2 outer inner1 inner2 is the same as pipe2 inner1 inner2 outer. (Equivalently, pipe2 is the same as flip . flip liftM2.)

commented

CyclopsMC/IntegratedTunnels#37 is a similar issue where more complex parameter handling is required.

I'll have to think about this a bit, to see what will be the best solution given the way ID currently works.

commented

I took a look at how the existing operator operators were implemented, and it'd take me a while to wrap my head around them. I don't think I have enough free time in the upcoming days to get it done in any reasonable amount of time.

commented

No worries, I won't have time for it myself in the near future anyways. So if you're interested in implementing it at any time, feel free to do so.

commented

We don't actually need user-defined functions to do what you need; we just need the S combinator (S = λxyz.xz(yz), called ap in Haskell):

haveEnough :: Item -> Boolean
haveEnough = ap (gt . size) haveAlready

Proof:

haveEnough = S (B gt size) haveAlready
haveEnough item = S (B gt size) haveAlready item
haveEnough item = (B gt size) item (haveAlready item)
haveEnough item = B gt size item (haveAlready item)
haveEnough item = gt (size item) (haveAlready item)

You could also do it if we added the W combinator (W = λxy.xyy, called join in Haskell):

haveEnough :: Item -> Boolean
haveEnough = join (flip (gt . size) . haveAlready)

Proof:

haveEnough = W (B (C (B gt size)) haveAlready)
haveEnough item = W (B (C (B gt size)) haveAlready) item
haveEnough item = (B (C (B gt size)) haveAlready) item item
haveEnough item = B (C (B gt size)) haveAlready item item
haveEnough item = (C (B gt size)) (haveAlready item) item
haveEnough item = C (B gt size) (haveAlready item) item
haveEnough item = (B gt size) item (haveAlready item)
haveEnough item = B gt size item (haveAlready item)
haveEnough item = gt (size item) (haveAlready item)
commented

@josephcsible Both function seem pretty useful in cases like these, so they are definitely worth implementing. Are you by any chance interested in implementing this yourself? You seem to have sufficient knowledge about the domain.

But still, user-defined functions might still be very useful when more complex user-defined operations are required.