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

Example usage of droste with expressions of varying inner types #178

Open
kthompson opened this issue Jul 23, 2020 · 3 comments
Open

Example usage of droste with expressions of varying inner types #178

kthompson opened this issue Jul 23, 2020 · 3 comments

Comments

@kthompson
Copy link

I have looked at higherkindness.athema.Expr[V, A] and it seems to provide type variable V for certain expressions.

I have an expression tree that I would like to define similar to above but what makes it unique is that there are at least five different base types if you will where expressions would require and only work with one of those base types. My thought was to define a type something like:

sealed trait Expr[A, B, C, D, E]
case class OpOnA[A, B, C, D, E](a: A) extends Expr[A, B, C, D, E]
case class CombineOnlyAsAndBs[A, B, C, D, E](a: A, b: B) extends Expr[A, B, C, D, E]
case class ConvertBToC[A, B, C, D, E](b: B, someValue: String) extends Expr[A, B, C, D, E]
case class RunC[A, B, C, D, E](c: C, time: Int) extends Expr[A, B, C, D, E]
...

Am I on the right track with the above? If so how do I use Fix with so many type parameters on Expr?

If not is there a more in depth example of droste that I can look at that has a similar constraint?

@pepegar
Copy link
Member

pepegar commented Jul 24, 2020

Hey @kthompson,

yeah, in the athema case, V represents the type of a value that may be contained within the Const constructor. It's parametrized because we want it to be defined by the user, not specified beforehand to , say, String. On the other hand, the other parameter A is the one used to tie the recursion knot.

In your case, I would need to see a more concrete example, but these look like a lot of different parameters to me. Can you be a bit more specific of what are you going to use these parameters for?

@kthompson
Copy link
Author

kthompson commented Jul 24, 2020

In my case it is for image manipulation.

Some operations would apply to single pixel values (Double), for example adding a value to increase brightness.

Some operations would only apply to Tiles. For example masking out a region of pixels.
Some operations work on arrays of Tiles for example computing RGB values.

An idea of the data model im working with:

case class Tile(values: Array[Double], rows: Int, cols: Int)
case class MultibandTile(bands: Array[Tile])
case class TileCollection(tiles: MultibandTile)

And some example expressions

sealed trait Expr[A]
case class SelectBand(tile: Expr[MultibandTile], index: Int) extends Expr[Tile]
case class CropTile(tile: Expr[Tile], extent: Extent) extends Expr[Tile]
case class ToMultiband(bands: Array[Expr[Tile]]) extends Expr[MultibandTile]
case class ComputeRGB(red: Expr[Tile], green: Expr[Tile], blue: Expr[Tile]) extends Expr[Tile]
case class SetNoDataValue(tile: Expr[MultibandTile], noDataValue: Double) extends Expr[MultibandTile]

So my problem comes in that we have in my example two operand types (Tile and MultibandTile).

If SelectBand were to become case class SelectBand(tile: A, index: Int) extends Expr[A] then that doesn't quite make sense as SelectBand only applies to MultibandTiles not Tiles.

Same goes for ToMultiband it doesnt make sense to combine multiple MultibandTiles into a MultibandTile, only multiple Tiles to a MultibandTile.

In ComputeRGB we want single bands for each channel MultibandTiles wouldnt work in this case as we wouldnt know which band to get.

My thought was that maybe i could do something like:

sealed trait Expr[T, M, C] // Tile, MultibandTile, Collection
case class SelectBand[T, M, C](tile: M, index: Int) extends Expr[T, M, C]
case class CropTile[T, M, C](tile: T, extent: Extent) extends Expr[T, M, C]
case class ToMultiband[T, M, C](bands: Array[T]) extends Expr[T, M, C]
case class ComputeRGB[T, M, C](red: T, green: T, blue: T) extends Expr[T, M, C]
case class SetNoDataValue[T, M, C](tile: M, noDataValue: Double) extends Expr[T, M, C]

If I do that though I am not really sure how to work in a Fix type or even if this properly constrains the types for my use case.

Hopefully this helps explain where I am running into an issue. Thanks!

@kthompson
Copy link
Author

This question is similar to mine but is more succinct: https://stackoverflow.com/questions/51073110/recursion-schemes-with-several-types/51073592#51073592

In my case I have Expr that refers to Stmt as well as Stmt that refers to Expr

ie:

sealed trait Expr
case class Block(stmts: List[Stmt], expr: Expr) extends Expr

sealed trait Stmt
case class ExprStmt(expr: Expr) extends Stmt

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

No branches or pull requests

2 participants