# Fun with object algebras and partial type application

This came up recently for me, I’ve made a toy example below.

Context:

I’ve got various object algebras that some system drives; depending on the context the object algebras deal with a `Result` that may be used for production or testing in different flavours of result. So here `Vector` is an example result used as a log.

There is a specific kind of result, `WrappedResult` that delegates to a simpler result; it adds some extra functionality. It is tested by wrapping it over an auditing result; expectations are applied to the auditing log. There are several different operations in the ‘real’ algebra, and it is important to show how the pass-through works, it is not always one-to-one for each operation.

(The reason for the auditing log is to finesse my current approach, namely using Mockito to supply the core result as a mock and using imperative verification to prove correctness of pure functional code. It works for me, but I feel bad about it, and it may come back to bite me later as things get more complex).

``````trait ObjectAlgebra[Result[_], Datum]:
def emptyResult: Result[Datum]
def add(partialResult: Result[Datum], datum: Datum): Result[Datum]
end ObjectAlgebra

class BigComplexAbstractingSystem[Result[_], Datum](
algebra: ObjectAlgebra[Result, Datum]
):
def calculationsGalore(data: Seq[Datum]): Result[Datum] =
// OK, just push data through the algebra to grow a result, it's a toy
// example here...
end BigComplexAbstractingSystem

val loggingAlgebra = new ObjectAlgebra[Vector, String]:
override def emptyResult: Vector[String] = Vector.empty

partialResult: Vector[String],
datum: String
): Vector[String] = partialResult :+ datum

case class WrappedResult[Result[_], Datum](
coreResult: Result[Datum],
extraStuff: String
)

def wrappingAlgebraTakeOne[CoreResult[_], Datum](coreAlgebra: ObjectAlgebra[CoreResult, Datum])
// Type argument WrappedResult[CoreResult, ?] does not have the same kind as its bound [_\$1]
: ObjectAlgebra[WrappedResult[CoreResult, _], Datum] = ???

type Fudge[CoreResult[_]] = [Datum] =>> WrappedResult[CoreResult, Datum]

def wrappingAlgebraTakeTwo[CoreResult[_], Datum](coreAlgebra: ObjectAlgebra[CoreResult, Datum])
: ObjectAlgebra[Fudge[CoreResult], Datum] = ???

``````

So the naive approach doesn’t compile, but after thinking of type lambdas and bashing my head against the keyboard a few times, I got `Fudge` and it compiles.

Great!

My question is, is there a more finessed way of defining the wrapping algebra? What was wrong with the first approach using partial type application that Scala 3 didn’t like?

Doh - `WrappedResult[CoreResult, _]` is an existential type, not a partially applied type. Got it.