Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#36 add interpreters to free #53

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

mr-calvert
Copy link
Owner

Addressing issue #36 to bootstrap all existing algebras with case class hierarchies to represent existing operations and then to add tagless interpreters which create Free programs via a new Embed typeclass (which stands in for Inject from specific FP libraries).

Can't output a Free program for unwrapped, eager operations; fixed.
Got the basic pattern down, and a pattern for algebras like the various
BufferIOs which use inheritance to share declarations of common blocks
of operations.
Demonstrates completion of the fbound operation pattern. Also
demonstrates how a leaf FreeIO interpreter gets built.
Found that *BufferIO in general weren't inheriting from *BufferReadIO
and they really should have been. This was letting Free*BufferIO not
implement *BufferReadIO, which is bad. Fixing the *BufferIO algebras
required refactoring ByteReadBufferFs and FreeByteReadBufferIO to be
extended by FreeByteBufferIO.
@mr-calvert
Copy link
Owner Author

Working on something else for a while, so here's the status:

  • Merged master (with polymorphic buffer algebras) in, as you can see above.
  • Fixed merge conflicts and committed locally.
  • Working on getting the Free stuff patched up vs the mods to the various buffer algebras.

The interesting puzzle of the moment is Lift, Term, and how to handle operations that take a polymorphic aligned interpreter as input. It highlights just how little I've thought through interpretation of Free programs into tagless interpreters. Exactly how state can be threaded through be the Free interpreter is unclear.

The polymophic buffer work makes FreeBufferIO significantly more
complex. This commit gets the project compiling by starting a bit of
the fix up and commenting out the rest of the FreeBufferIO file.

Sebsequent commits will work towards making FreeBufferIO, Lift, and
Term play together with the alignment type. Should be an adventure.
In the branch I'd put bounds on the alignment type parameter, forcing
it to be the Module. In the case of ByteBuffer it's the whole Buffer
system Module. For the others it's their type specific Module. The
bound allows the algebra definitions in the IO traits to return full
leaf types. The trouble is it really complicated the Lift/Term
declarations as the bounds had to be recreated to ensure soundness.
That was gonna be UGLY and the pay off was exposing leaf types from
interpreters which probably isn't even a good idea.

In this commit we allow the alignment parameter to be unrestrained.
This prevents type projection into the Module to define f-bound return
types from operations that accept and return interpreter instances.
That's fine as we have the algebra trait types, with their alignment
parameters. In this commit all the f-bound operations are modified to
use the abstract algebra trait type and the alignment type.

This still uses the alignment type to prevent a FreeByteBufferIO
interpreter from being passed into the JVM interpreter's .read method
for instance. It just doesn't give up the actual runtime type of the
returned interpreter, which is probably better anyway.
When I tried to carry unrestricted alignment types to the FileIO and
FSIO interfaces I ran into the wall because those interfaces relied on
the alignment type being bound to a Module type to align the multiple
algebras it depends on.

I then realized that we don't need really fine grained alignment, we
just need to ensure that Free interpreters are passed Free
interpreters and Java backed interpreters are passed Java backed
interpreters. There won't be 6 competing and incompatible Java backed
interpreters, ever. So instead of silently using the JVMBufferIOModule
type to align Buffers (and then being out of luck when we get to
FileIO/FSIO) I created a new single purpose JVMA type in the root of
the Java API package.

Any interpreter which implements a wrapped Java library's algebra by
deferring directly to the Java implementation can be tagged with this
dedicated alignment type.
@mr-calvert
Copy link
Owner Author

So I've solved the problem with polymorphic aligned interpreters as arguments and results from algebra operations. It took refactoring the whole code base to use unrestricted alignment types and pretty much gutted the Module system.

There are two big bang commits with this work. They were the only two intermediate "compiles and runs" points in the whole job. There's a bunch of clean up left; heck I've not even closely read the diffs from the second commit. My plan is to do a detailed review now that it's committed and go back to working incrementally while cleaning up whatever dreck I find.

FSPathLogic took a heavy reworking to take the IO[_[_], _] shape. I
removed the operation to create a Path from a String because that was
the only one that really needed FSPathLogic to wrap a FileSystem
object. Right now the examples are cheesed together using the
IsoImmutableUnsafe instance for FSPath, which doesn't create FSPath.P
instances with correct D domain labling types.

The better way to create FSPath.P instances is to use the (not yet
created) FileSystem algebra. That's for the future though.

Other than that this commit is a ton of nuking Modules as alignment
types and adding JVMA and FreeA. And gutting Modules. I'm glad I never
cleaned up the Modules. I suspect they'll mostly go away with the new
alignment types approach.
The fun thing here is adding TermP1 (Term/Polymorphic/Order 1) to put
select (instead of selectA) into the F1 term trait for non
algebra/polymorphic result types within an algebra that ALSO has
algebra/polymorphic types. Nice to reduce a bit of boilerplate.
Eliminated a few more spurious A's
Why'd I stop? ByteBufferIO.putBuffer(ByteBufferReadIO) pretty much
breaks what we're doing. Term is configured to be polymorphic in the
target interpreter's alignment parameter, which is fine. Trouble is
putBuffer, and many other operations in the FileIO algebras that
require input parameters that are aligned interpreters. Free requires
the inputs be stored which happens BEFORE the polymorphic call to
Term.select.

I'm not sure what I'm going to do.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant