2 ms·
Yep, the multiple same type issue definitely happens and that compicates client side matching. In my experience it has been infrequent enough that having to mak
by benjaminjackman 12y ago
Yep, the multiple same type issue definitely happens and that compicates client side matching. In my experience it has been infrequent enough that having to make the a couple wrapper classes would be preferable. Sometime tuples can be very ambiguous, take points for example. Point(x:Int,y:Int) is similar to (Int,Int), however sometimes the anonymity is nice so you will want to have both options.
The Boilerplate grows really fast as you try to pass results up a call hierachy.
So let me extend the example to demonstrate it how it doesn't scale:
//Sorry for the Scala-ness
//Presume a mapByType partial function on all discriminated unions if the union value is of that type, then it calls
//the partial function otherwise it just returns whatever it's current value is
def lexAndParse : ParseError | LexError | Int | String = lex().mapByType{ case t : Token => parse(t) }
newtype LexError = Err
def lex() : LexError | Token = ...
newtype ParseError = Err
def parse(t : Token) : ParseError | Int | String = {
tryParseInt(t).orElse(tryParseString(t)).getOrElse(ParseError("$t not Int Or String"))) }
}
def tryParseInt(token : Token) : Option[Int] = ...
def tryParseString(token : Token) : Option[String] = ...
versus:
pub enum LexParseResult {
LexError(Err)
ParseError(Err)
IntResult(Int)
StringResult(String)
}
def lexAndParse : LexAndParseResult = {
match lex() {
LexResult.LexError(e) => LexAndParseResult.LexError(e)
LexResult.TokenResult(t) => match parse(t) {
ParseResult.ParseError(e) => LexParseResult.ParseError(e)
ParseResult.IntResult(e) => LexParseResult.IntResult(e)
ParseResult.StringResult(e) => LexParseResult.StringResult(e)
}
}
}
pub enum LexResult {
LexError(Err)
TokenResult(Token)
}
def lex : LexResult
pub enum ParseResult {
ParseError(Err)
IntResult(Int)
StringResult(String)
}
def parse(token : Token) : ParseResult = {
match lex(){
Token(t) =>
tryParseInt(t).map(r=>ParseResult.IntResult(r)).orElse(tryParseString.map(r=>ParseResult.StringResult(r) )).getOrElse(ParseResult.ParseError("$t not Int Or String"))) }
LexError(e) => ParseResult.LexError(e)
}
}
def tryParseInt(token : Token) : Option[Int] = ...
def tryParseString(token : Token) : Option[String] = ...