On Thu, 22 Feb 2018 12:55:01 +0000 Jesper Louis Andersen
<[email protected]> wrote:
>
> For sums, in Go, I have to return a pair,
>
> x, err := someOperation(..)
>
> but this is slightly inconsistent, insofar I can return "nil, nil", which
> might not be a valid value, or I can return "3, Error(..)" but in that case
> the 3 is not to be used. Only one "side" is valid at a given point in time.
> If you have sum-types in the usual sense, you can define something along
> the lines of (OCaml follows):
>
> type ('a, 'b) result = Ok of 'a | Error of 'b
I once worked out some details of adding sum types to Go and I
think it is quite doable and easy to implement. For example,
func f(i int) float64|error {
if i == 0 { return errors.New("not zero") }
return 1./float64(i)
}
As in OCaml "|" is used for sum types and it binds less
tightly than existing type "expressions".
> And then you can discriminate on this value via pattern matching
>
> match res with
> | Ok value -> ...
> | Error err -> ...
Not quite the same but something similar is doable with
type switch.
res := f(j)
switch res.(type) {
case error: ...
case string: ...
}
This use is identical with f returning interface{} (even the f
body remains exactly the same). This makes sense since
interface{} is in a sense the sum of all other types.
But by allowing sum type, we can do better checking within f
(e.g. return "string" will fail to compile). And by using a
sum type instead of a product type to return a value or error
also makes the code clearer.
I once counted there were about 8000 uses of <type>,error as
return types for functions in $GOROOT/src which could benefit
from sum types. Now there seem to be about 4253 instances
(found using a crude regexp).
I think I worked out the semantics of T1|T2 where T1 and T2
are both interface types themselves. It all seem to fit
together, at least on paper! I need to find my notes....
> The other matching construction is a switch-statement, but such a statement
> doesn't allow for matching deeply into an AST structure, which a
> traditional pattern matcher does.
Deeper matching also binds names to matched parts. e.g.
sumsqr [] = 0
sumsqr (x:xs) = x*x + sumsqr xs
This sort of binding may be difficult to shoehorn into Go.
There may be no real benefit of binding head, tail of a slide
but consider an AST. If you are already cracking it open for
matching it with a pattern, you may as well bind variables to
interesting parts.
match stmt {
case If1stmt(test:, thenstmt:): ...
case If2stmt(test:, thenstmt:, elsestmt:): ...
...
}
Hard to come up with an intuitive syntax here. Also probably
impossible to add func level patterns.
> Coincidentally, given sum-types, you can write a regexp matching engine in
> very few lines of code. See Bob Harper's "Programming in Standard ML" [2]
> for example; it is the introductory example to get a feel for the language.
> The solution uses sum types to define the AST for regular expressions, and
> then uses pattern matching to build a matcher on regular expressions. I
> can't remember how far Bob takes the exposition however.
This should be doable given my sum-type proposal sketch above?!
> [0] They are really the same in the right setting. In a boolean algebra,
> for instance, + is OR and * is AND. If you look at them from the Category
> Theory branch of mathematics they are related: they are duals of each other
> which means that if you "invert" one you get the other and vice versa.
>
> [1] Obviously, Go, being a descendant of Algol has two syntactic classes:
> statements and expressions, whereas OCaml is descendant from either Lisp or
> the Lambda Calculus depending on view. Those languages only have
> expressions as a syntactic class.
sum-types (which are easy to implement) and pattern matching
(may be not so easy) can be added to Go even if it has
non-expression syntatic classes.
> [2] http://www.cs.cmu.edu/~rwh/isml/book.pdf
>
> [3]
> https://www.microsoft.com/en-us/research/wp-content/uploads/1987/01/slpj-book-1987-small.pdf
SLPJ's book was quite an eye opener for me back in the '80s!
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.