Fp-ts: How to write Eq for an union?

Created on 11 Nov 2020  路  4Comments  路  Source: gcanti/fp-ts

馃摉 Documentation

Is this idiomatic fp-ts?

const eqNode: Eq<Text | ElementNotNormalized> = fromEquals((x, y) => {
  if (x.type === 'text') {
    if (y.type === 'element') return false;
    return eqText.equals(x, y);
  } else {
    if (y.type === 'text') return false;
    return eqElement.equals(x, y);
  }
});

Most helpful comment

Because you appear to be testing discriminated unions, this is functionally identical to how Eq instances are derived for the likes of Either in fp-ts. There's really no way to do this other than to check against your discriminant as you are doing.

My only suggestion would be to line up the conditions slightly so that it's more readable and scales better:

const eqNode: Eq<Text | ElementNotNormalized> = fromEquals((x, y) => {
  if (x.type === 'text' && y.type === 'text') return eqText.equals(x, y);
  if (x.type === 'element' && y.type === 'element') return eqElement.equals(x, y);
  return false;
});

All 4 comments

I do it myself the same way, but use a ADT library like morphic-ts or use a switch statements instead of if

const eqNode: Eq<Text | ElementNotNormalized> = fromEquals((x, y) => {
  switch (x.type) {
    case 'element': return y.type === 'element' && eqElement.equals(x, y)
    case 'text': return y.type === 'text' && eqText.equals(x, y)
  }
});

@mlegenhausen Thank you. But this approach can explode if we have more than two unioned types, so I am curious if there is any generic way of doing that for n types.

Because you appear to be testing discriminated unions, this is functionally identical to how Eq instances are derived for the likes of Either in fp-ts. There's really no way to do this other than to check against your discriminant as you are doing.

My only suggestion would be to line up the conditions slightly so that it's more readable and scales better:

const eqNode: Eq<Text | ElementNotNormalized> = fromEquals((x, y) => {
  if (x.type === 'text' && y.type === 'text') return eqText.equals(x, y);
  if (x.type === 'element' && y.type === 'element') return eqElement.equals(x, y);
  return false;
});

@samhh That makes sense. Thank you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Crashthatch picture Crashthatch  路  4Comments

vicrac picture vicrac  路  4Comments

josete89 picture josete89  路  3Comments

denistakeda picture denistakeda  路  4Comments

steida picture steida  路  4Comments