a simple way for polymorphism and structured programming - go interfaces
TRANSCRIPT
A simple way for polymorphism and structuredprogramming
Polymorphism in Go
Robert Zaremba
AgFlow
Wroc law 2015-01-08
Me
ii
Studied MSc of Computer Science at University of Wroclawhttp://rz.scale-it.pl
Profession
CTO @ AgFlowCoding professionally in Go, Python, HaskellCo-organizer of Geneva Haskell Group
Hiring
We are doing a world commodities market analysis. Contact me ifyou are looking for an interesting job.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 2 / 29
What is a Polymorphism?OOP
In object-oriented programming, polymorphism refers to aprogramming language’s ability to process objects differentlydepending on their data type or class.For example, given a base class shape, polymorphism enables theprogrammer to define different area methods for any number ofderived classes, such as circles, rectangles and triangles.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 3 / 29
What is a Polymorphism?Biology
Morph
Greek: form, shape.Is a visual or behavioural difference between organisms of distinctpopulations.
Polymorphism in biology occurs when two or more clearly differentphenotypes exist in the same population of a species.In order to be classified as such, morphs must occupy the samehabitat at the same time and belong to a panmictic population (allindividuals are potential partners).
Also
Molecular biologists use that term to describe certain point mutationsin the genotype.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 4 / 29
What is a Polymorphism?Biology
Morph
Greek: form, shape.Is a visual or behavioural difference between organisms of distinctpopulations.
Polymorphism in biology occurs when two or more clearly differentphenotypes exist in the same population of a species.In order to be classified as such, morphs must occupy the samehabitat at the same time and belong to a panmictic population (allindividuals are potential partners).
Also
Molecular biologists use that term to describe certain point mutationsin the genotype.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 4 / 29
What is a Polymorphism?Computer Science
Algebra revision
A structure-preserving map from one mathematical structure toanother.
Programming Languages and type theory revision
provision of a single interface to entities of different types.
Key feature:A value is polymorphic if there is more than one type itcan have.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 5 / 29
What is a Polymorphism?Computer Science
Algebra revision
A structure-preserving map from one mathematical structure toanother.
Programming Languages and type theory revision
provision of a single interface to entities of different types.
Key feature:A value is polymorphic if there is more than one type itcan have.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 5 / 29
What is a Polymorphism?Computer Science
Algebra revision
A structure-preserving map from one mathematical structure toanother.
Programming Languages and type theory revision
provision of a single interface to entities of different types.
Key feature:A value is polymorphic if there is more than one type itcan have.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 5 / 29
Polymorphism ≡ multiple types?
What does it mean that value can have more
then one type?
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 6 / 29
Polymorphism ≡ multiple types?Parametric polymorphism
Parametric polymorphism
Type of a value contains one or more (unconstrained) type variables.
id: a -> a
data pair a b = Pair a b
type unification!
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 7 / 29
Polymorphism ≡ multiple types?Parametric polymorphism
Parametric polymorphism
Type of a value contains one or more (unconstrained) type variables.
id: a -> a
data pair a b = Pair a b
type unification!
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 7 / 29
Polymorphism ≡ multiple types?Parametric polymorphism
Parametric polymorphism
Type of a value contains one or more (unconstrained) type variables.
id: a -> a
data pair a b = Pair a b
type unification!
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 7 / 29
Polymorphism ≡ multiple types?Ad-hoc polymorphism
Ad-hoc polymorphism
A value is able to adopt any one of several types.Eg. because it, or a value it uses, has been given a separate definitionfor each of those types
function multiple dispatch (C, Julia, . . . )
function multiple dispatch build in a language (eg buildingoperators overloading: +, -, *, ...
type classes
traits
lambda calculus with parametric polymorphism
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 8 / 29
Polymorphism ≡ multiple types?Ad-hoc polymorphism
Ad-hoc polymorphism
A value is able to adopt any one of several types.Eg. because it, or a value it uses, has been given a separate definitionfor each of those types
function multiple dispatch (C, Julia, . . . )
function multiple dispatch build in a language (eg buildingoperators overloading: +, -, *, ...
type classes
traits
lambda calculus with parametric polymorphism
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 8 / 29
Polymorphism ≡ multiple types?Ad-hoc polymorphism
Ad-hoc polymorphism
A value is able to adopt any one of several types.Eg. because it, or a value it uses, has been given a separate definitionfor each of those types
function multiple dispatch (C, Julia, . . . )
function multiple dispatch build in a language (eg buildingoperators overloading: +, -, *, ...
type classes
traits
lambda calculus with parametric polymorphism
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 8 / 29
Polymorphism ≡ multiple types?Ad-hoc polymorphism
Ad-hoc polymorphism
A value is able to adopt any one of several types.Eg. because it, or a value it uses, has been given a separate definitionfor each of those types
function multiple dispatch (C, Julia, . . . )
function multiple dispatch build in a language (eg buildingoperators overloading: +, -, *, ...
type classes
traits
lambda calculus with parametric polymorphism
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 8 / 29
Polymorphism ≡ multiple types?Ad-hoc polymorphism
Ad-hoc polymorphism
A value is able to adopt any one of several types.Eg. because it, or a value it uses, has been given a separate definitionfor each of those types
function multiple dispatch (C, Julia, . . . )
function multiple dispatch build in a language (eg buildingoperators overloading: +, -, *, ...
type classes
traits
lambda calculus with parametric polymorphism
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 8 / 29
Polymorphism ≡ multiple types?Subtyping
Well known inheritance.
Hate
What was first: a chicken or an egg?
class Animal abstract String talk(); abstract
move(int, int)
Only Animals can talk? All animals can talk? What about voiceproducing?
http://www.scala-lang.org/api/current/#scala.collection.Map — problem with inheritance hierarchy
trait Map[A, +B] extends Iterable[(A, B)] with
GenMap[A, B] with MapLike[A, B, Map[A, B]]
trait Iterable[+A] extends Traversable[A] with
GenIterable[A] with GenericTraversableTemplate[A,
Iterable] with IterableLike[A, Iterable[A]]
Traversable, GenIterable, . . . “state of the art”? WTF??
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 9 / 29
Polymorphism ≡ multiple types?Subtyping
Well known inheritance.
Hate
What was first: a chicken or an egg?
class Animal abstract String talk(); abstract
move(int, int)
Only Animals can talk? All animals can talk? What about voiceproducing?
http://www.scala-lang.org/api/current/#scala.collection.Map — problem with inheritance hierarchy
trait Map[A, +B] extends Iterable[(A, B)] with
GenMap[A, B] with MapLike[A, B, Map[A, B]]
trait Iterable[+A] extends Traversable[A] with
GenIterable[A] with GenericTraversableTemplate[A,
Iterable] with IterableLike[A, Iterable[A]]
Traversable, GenIterable, . . . “state of the art”? WTF??
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 9 / 29
Polymorphism ≡ multiple types?Subtyping
Well known inheritance.
Hate
What was first: a chicken or an egg?
class Animal abstract String talk(); abstract
move(int, int)
Only Animals can talk? All animals can talk? What about voiceproducing?
http://www.scala-lang.org/api/current/#scala.collection.Map — problem with inheritance hierarchy
trait Map[A, +B] extends Iterable[(A, B)] with
GenMap[A, B] with MapLike[A, B, Map[A, B]]
trait Iterable[+A] extends Traversable[A] with
GenIterable[A] with GenericTraversableTemplate[A,
Iterable] with IterableLike[A, Iterable[A]]
Traversable, GenIterable, . . . “state of the art”? WTF??
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 9 / 29
Polymorphism ≡ multiple types?Subtyping
Well known inheritance.
Hate
What was first: a chicken or an egg?
class Animal abstract String talk(); abstract
move(int, int)
Only Animals can talk? All animals can talk? What about voiceproducing?
http://www.scala-lang.org/api/current/#scala.collection.Map — problem with inheritance hierarchy
trait Map[A, +B] extends Iterable[(A, B)] with
GenMap[A, B] with MapLike[A, B, Map[A, B]]
trait Iterable[+A] extends Traversable[A] with
GenIterable[A] with GenericTraversableTemplate[A,
Iterable] with IterableLike[A, Iterable[A]]
Traversable, GenIterable, . . . “state of the art”? WTF??
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 9 / 29
Polymorphism ≡ multiple types?Subtyping
Well known inheritance.
Hate
What was first: a chicken or an egg?
class Animal abstract String talk(); abstract
move(int, int)
Only Animals can talk? All animals can talk? What about voiceproducing?
http://www.scala-lang.org/api/current/#scala.collection.Map — problem with inheritance hierarchy
trait Map[A, +B] extends Iterable[(A, B)] with
GenMap[A, B] with MapLike[A, B, Map[A, B]]
trait Iterable[+A] extends Traversable[A] with
GenIterable[A] with GenericTraversableTemplate[A,
Iterable] with IterableLike[A, Iterable[A]]
Traversable, GenIterable, . . . “state of the art”? WTF??
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 9 / 29
Polymorphism ≡ multiple types?Subtyping
Well known inheritance.
Hate
What was first: a chicken or an egg?
class Animal abstract String talk(); abstract
move(int, int)
Only Animals can talk? All animals can talk? What about voiceproducing?
http://www.scala-lang.org/api/current/#scala.collection.Map — problem with inheritance hierarchy
trait Map[A, +B] extends Iterable[(A, B)] with
GenMap[A, B] with MapLike[A, B, Map[A, B]]
trait Iterable[+A] extends Traversable[A] with
GenIterable[A] with GenericTraversableTemplate[A,
Iterable] with IterableLike[A, Iterable[A]]
Traversable, GenIterable, . . . “state of the art”? WTF??
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 9 / 29
Polymorphism ≡ multiple types?Subtyping
Well known inheritance.
Hate
What was first: a chicken or an egg?
class Animal abstract String talk(); abstract
move(int, int)
Only Animals can talk? All animals can talk? What about voiceproducing?
http://www.scala-lang.org/api/current/#scala.collection.Map — problem with inheritance hierarchy
trait Map[A, +B] extends Iterable[(A, B)] with
GenMap[A, B] with MapLike[A, B, Map[A, B]]
trait Iterable[+A] extends Traversable[A] with
GenIterable[A] with GenericTraversableTemplate[A,
Iterable] with IterableLike[A, Iterable[A]]
Traversable, GenIterable, . . . “state of the art”? WTF??
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 9 / 29
Polymorphism ≡ multiple types?Subtyping
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 10 / 29
Polymorphism ≡ multiple types?Subtyping
Interfaces come to rescue!
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 10 / 29
Polymorphism ≡ multiple types?Subtyping
And Scalas implicits
1 implicit def intToX(i: Int) = new X(i)
Really?
1 def newTask = Action { implicit request =>
2 taskForm.bindFromRequest.fold(
3 errors => BadRequest(views.html.index(Task.all(), errors)),
4 label => {
5 Task.create(label)
6 Redirect(routes.Application.tasks())
7 }
8 )
9 }
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 11 / 29
Polymorphism ≡ multiple types?Subtyping
And Scalas implicits
1 implicit def intToX(i: Int) = new X(i)
Really?
1 def newTask = Action { implicit request =>
2 taskForm.bindFromRequest.fold(
3 errors => BadRequest(views.html.index(Task.all(), errors)),
4 label => {
5 Task.create(label)
6 Redirect(routes.Application.tasks())
7 }
8 )
9 }
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 11 / 29
Go programming languageGo is simple
Go is a super simple programming language
C-like
no inheritance
just functions
GC - a lot of heavy work has been done
awesome concurrency
static typed
https://golang.org/ref/spec 75 pagescompare to C++ spec: 1368 pages
zen of Go
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 12 / 29
Go programming languageScope
We will not talk about awesome concurrencyWe will talk about dynamic interfaces.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 13 / 29
Go InterfacesWhat is an interface in Go
Interfaces in Go
A simple, limited form of ad-hoc polymorphism. They provide a wayto specify the behavior of an object: if something can do this, then itcan be used here.
Type overview:
pragmatic type system
trade-off between scope bound OOP and super-hiper-fancy hardtype systems (hard Haskell, wtf Scala, having almost everythingC++).
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 14 / 29
Go InterfacesWhat is an interface in Go
Interfaces in Go
A simple, limited form of ad-hoc polymorphism. They provide a wayto specify the behavior of an object: if something can do this, then itcan be used here.
Type overview:
pragmatic type system
trade-off between scope bound OOP and super-hiper-fancy hardtype systems (hard Haskell, wtf Scala, having almost everythingC++).
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 14 / 29
Go InterfacesWhat is an interface in Go
Interfaces in Go
A simple, limited form of ad-hoc polymorphism. They provide a wayto specify the behavior of an object: if something can do this, then itcan be used here.
Type overview:
pragmatic type system
trade-off between scope bound OOP and super-hiper-fancy hardtype systems (hard Haskell, wtf Scala, having almost everythingC++).
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 14 / 29
Go Interfaces
1 package main
2 import (
3 "fmt"
4 "math"
5 )
6
7 type Vertex struct {
8 X, Y float64
9 }
10
11 func (v *Vertex) Abs() float64 {
12 return math.Sqrt(v.X*v.X + v.Y*v.Y)
13 }
14
15 func main() {
16 v := &Vertex{3, 4}
17 fmt.Println(v.Abs())
18 }
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 15 / 29
Go Interfaces
1 type Abser interface {
2 Abs() float64
3 }
4 type MyFloat float64
5 func (f MyFloat) Abs() float64 {
6 if f < 0 {
7 return float64(-f)
8 }
9 return float64(f)
10 }
11 func main() {
12 var a Abser
13 f := MyFloat(-math.Sqrt2)
14 v := Vertex{3, 4}
15 a = f // a MyFloat implements Abser
16 a = &v // a *Vertex implements Abser
17 // In the following line, v is a Vertex (not *Vertex)
18 // and does NOT implement Abser.
19 a = v
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 16 / 29
Go Interfaces
Interfaces are implicit
A type implements an interface by implementing the methods. Thereis no ”implements” keyword.Implicit interfaces decouple implementation packages from thepackages that define the interfaces: neither depends on the other.
Unlike Haskell you don’t need to explicitly implement type classes.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 17 / 29
Go Interfaces
Minimalism and compose-ability
Like in haskell you are encourage to declare minimum meaningfulinterfaces and compose them.
1 type Reader interface {
2 Read(b []byte) (n int, err error)
3 }
4
5 type Writer interface {
6 Write(b []byte) (n int, err error)
7 }
8
9 type ReadWriter interface {
10 Reader
11 Writer
12 }
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 18 / 29
Go Interfaces
Alternative implementations
Like in Haskell you need to wrap types if you want to provide morethen one implementation of some interface.
1 type VertexManhattan {
2 Vertex
3 }
4
5 func (v *VertexManhattan) Abs() float64 {
6 return MyFloat(v.X).Abs() + MyFloat(v.Y).Abs()
7 }
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 19 / 29
Go Interfaces
Minimalism and API clarity
Ideally all your packages should expose interface values.All your package functions should take interfaces instead of structtypes.
Interface upgrades
There is a powerful feature - interface updates. From the minimumimplementation you can check more powerful object features bychecking which other interfaces are implemented from a minimumtype.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 20 / 29
Go dynamic Interfaces
dynamic type
Go types can be cast to wider or even unrelated interfaces if theirdynamic types support it.Duck duck typing!
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 21 / 29
Go dynamic Interfaces
The io package defines two auxiliary types, io.WriterTo andio.ReaderFrom which io.Readers and io.Writers (respectively) mayoptionally implement.
1 func Copy(dst Writer, src Reader) (written int64, err error) {
2 // If the reader has a WriteTo method, use it to
3 // do the copy. Avoids an allocation and a copy.
4 if wt, ok := src.(WriterTo); ok {
5 return wt.WriteTo(dst)
6 }
7 // Similarly, if the writer has a ReadFrom method,
8 // use it to do the copy.
9 if rt, ok := dst.(ReaderFrom); ok {
10 return rt.ReadFrom(src)
11 }
12 ...
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 22 / 29
Go dynamic Interfaces
1 buf := make([]byte, 32*1024)
2 for {
3 nr, er := src.Read(buf)
4 if nr > 0 {
5 nw, ew := dst.Write(buf[0:nr])
6 if nw > 0 {
7 written += int64(nw)
8 }
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 23 / 29
Go interfaces trap
1 type StatusLogger struct {
2 http.ResponseWriter
3 StatusCode int
4 }
5
6 func (s *StatusLogger) WriteHeader(code int) {
7 s.StatusCode = code
8 s.ResponseWriter.WriteHeader(code)
9 }
StatusLogger only implements http.ResponseWriter, even sothe underlying object may implement rich functionality.
it doesn’t implement any interface upgrades. Using it you willnot provide all performance characteristics (eg. throughReaderFrom) even the underlying response writer will providethem.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 24 / 29
Go interfaces trap
1 type StatusLogger struct {
2 http.ResponseWriter
3 StatusCode int
4 }
5
6 func (s *StatusLogger) WriteHeader(code int) {
7 s.StatusCode = code
8 s.ResponseWriter.WriteHeader(code)
9 }
It is impossible to write a general-purpose proxy type.
All proxy interfaces will hide possible interface updates
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 24 / 29
Go interfaces trap
1 type StatusLogger struct {
2 http.ResponseWriter
3 StatusCode int
4 }
5
6 func (s *StatusLogger) WriteHeader(code int) {
7 s.StatusCode = code
8 s.ResponseWriter.WriteHeader(code)
9 }
Solution: you will need to manually implement a new structurewhich will satisfy a richer interface, as shown in the example below.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 24 / 29
Writing a proxy objectWrapping a ResponseWriter
A Writer wrapper from Goji web framework.
1 // WrapWriter wraps an http.ResponseWriter into a proxy that
2 // allows you to hook into various parts of the response process.
3 func WrapWriter(w http.ResponseWriter) WriterProxy {
4 _, cn := w.(http.CloseNotifier)
5 _, fl := w.(http.Flusher)
6 _, hj := w.(http.Hijacker)
7 _, rf := w.(io.ReaderFrom)
8 bw := basicWriter{ResponseWriter: w}
9 if cn && fl && hj && rf {
10 return &fancyWriter{bw}
11 }
12 return &bw
13 }
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 25 / 29
Writing a proxy objectBasic writer in action
1 func (b *basicWriter) Write(buf []byte) (int, error) {
2 b.WriteHeader(http.StatusOK)
3 n, err := b.ResponseWriter.Write(buf)
4 if b.tee != nil {
5 _, err2 := b.tee.Write(buf[:n])
6 // Prefer errors generated by the proxied writer.
7 if err == nil {
8 err = err2
9 }
10 }
11 b.bytes += n
12 return n, err
13 }
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 26 / 29
Writing a proxy objectFancy writer in Action
1 type fancyWriter struct {
2 basicWriter
3 }
4 func (f *fancyWriter) CloseNotify() <-chan bool {
5 cn := f.basicWriter.ResponseWriter.(http.CloseNotifier)
6 return cn.CloseNotify()
7 }
8 func (f *fancyWriter) Flush() {
9 ...}
10 func (f *fancyWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
11 ...}
12 func (f *fancyWriter) ReadFrom(r io.Reader) (int64, error) {
13 if f.basicWriter.tee != nil {
14 return io.Copy(&f.basicWriter, r)
15 }
16 rf := f.basicWriter.ResponseWriter.(io.ReaderFrom)
17 f.basicWriter.maybeWriteHeader()
18 return rf.ReadFrom(r)
19 }Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 27 / 29
Go interfaces limitations
No parametric polymorphism and limited Ad-hoc polymorphism.In 99% of cases you won’t need it!
Workaround: go generate
A real solution may come as soon as people will find an easypolymorphic type system which will integrate well with go interfaces.By now go generate is making a good job for this corner cases.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 28 / 29
Go interfaces limitations
No parametric polymorphism and limited Ad-hoc polymorphism.In 99% of cases you won’t need it!
Workaround: go generate
A real solution may come as soon as people will find an easypolymorphic type system which will integrate well with go interfaces.By now go generate is making a good job for this corner cases.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 28 / 29
Go interfaces limitations
No parametric polymorphism and limited Ad-hoc polymorphism.In 99% of cases you won’t need it!
Workaround: go generate
A real solution may come as soon as people will find an easypolymorphic type system which will integrate well with go interfaces.By now go generate is making a good job for this corner cases.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 28 / 29
Summary
A simple type system based on dynamic interfacesprovides a powerful tool for software architects whichwill help design and maintain software systems.
Idea for OOP:Unless you want to extend / wrap some object it maybe interesting to use only abstract inheritance in OOP.
Robert Zaremba (AgFlow) Simple polymorphism Wroc law 2015-01-08 29 / 29