Skip to content

Instantly share code, notes, and snippets.

@nodinosaur
Created January 1, 2020 17:08
Show Gist options
  • Save nodinosaur/817656fdfeb2cb3e7e9ce2e68e26b090 to your computer and use it in GitHub Desktop.
Save nodinosaur/817656fdfeb2cb3e7e9ce2e68e26b090 to your computer and use it in GitHub Desktop.
Recoded Sum Types example
// Root
import 'package:meta/meta.dart';
import 'package:sealed_unions/sealed_unions.dart';
/// ======================================================================
/// Everything above this line is a Doublet & Triplet Sealed Union thing
/// ======================================================================
enum UsState { florida }
enum CaProvince { ontario }
class PostalInfo {
String street;
StateOrProvince stateOrProvince;
PostalInfo({
@required this.street,
@required this.stateOrProvince,
}) : assert(street != null),
assert(stateOrProvince != null);
@override
String toString() => 'PostalInfo street: $street, stateOrProvince: $stateOrProvince';
}
class StateOrProvince extends Union2Impl {
StateOrProvince(Union2 union) : super(union);
// PRIVATE low-level factory
// Used for instantiating individual "subclasses"
static final Doublet<UsState, CaProvince> _factory = const Doublet<UsState, CaProvince>();
// PRIVATE constructor which takes in the individual weather states
StateOrProvince._(Union2<UsState, CaProvince> union) : super(union);
// PUBLIC factories which hide the complexity from outside classes
factory StateOrProvince.usState(UsState state) => StateOrProvince._(_factory.first(state));
factory StateOrProvince.caProvince(CaProvince province) => StateOrProvince._(_factory.second(province));
@override
String toString() => join(
(state) => '$state',
(province) => '$province',
);
}
void main() {
// Correct
final postalInfoUS = PostalInfo(
street: 'Some US Street',
stateOrProvince: StateOrProvince.usState(UsState.florida),
);
print(postalInfoUS);
// Correct
final postalInfoCA = PostalInfo(
street: 'Some Canadian Street',
stateOrProvince: StateOrProvince.caProvince(CaProvince.ontario),
);
print(postalInfoCA);
sendLetter(postalInfoUS);
sendLetter(postalInfoCA);
}
void sendLetter(PostalInfo postalInfo) {
postalInfo.stateOrProvince.join(
(usState) {
printLetter(postalInfo);
shipLetterUSPS();
},
(caProvince) {
printLetter(postalInfo);
shipLetterCanadaPost();
},
);
}
void printLetter(PostalInfo postalInfo) {
// Imagine this prints a physical letter...
print(
'''
*******
${postalInfo.street}
${postalInfo.stateOrProvince.toString()}
Yours truly,
The Chief
*******
''',
);
}
void shipLetterUSPS() {
print('Shipping to United States\n\n');
}
void shipLetterCanadaPost() {
print('Shipping to Canada\n\n');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment