propensive / wisteria

Easy, fast, transparent generic derivation of typeclass instances in Scala
https://soundness.dev/wisteria/
20 stars 2 forks source link

Provide a more general `constructWith` method #9

Closed propensive closed 4 months ago

propensive commented 4 months ago

The construct method is currently the only way to make a new instance of a derivation type in Wisteria. It takes a lambda to be applied to each field, returning an instance of that field type. But this makes it inconvenient to derive a typeclass such as,

trait Parser[ValueType]:
  def parse(string: String): Either[Exception, ValueType]

where the return type of the context typeclass is a more complex type construction of the field type.

The API for constructWith will need to be a bit more complex than construct. It will need to take a lambda which operates on a field-by-field basis.

I think it should look something like this at the call-site:

constructWith[Either[Exception, _]]:
  [FieldType] =>
    context.parse(input) match
      case Left(err)    => Left(err)
      case Right(value) => specify(value)(Right(_))

where the lambda is [FieldType] => <context> ?=> Either[Exception, DerivationType], and the specify function value is provided in context. The specify(value)(Right(_)) application is basically says "include the field value value in the result, and continue to the next field, and when we're done, wrap the result in Right(_)".

propensive commented 4 months ago

An alternative would be:

constructWith[Either[Exception, _]](Right(_)):
  [FieldType] =>
    context.parse(input) match
      case Left(err)    => Left(err)
      case Right(value) => specify(value)

This might be a bit more logical.