Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go Lift

Go Lift

A talk that's secretly about Category Theory, delivered at dotGo 2017

John Cinnamond

November 06, 2017
Tweet

More Decks by John Cinnamond

Other Decks in Programming

Transcript

  1. conn, err := net.Dial(”tcp”, ”server:9876”) if err != nil {

    panic(err) } , err := conn.Write(command1)
  2. conn, err := net.Dial(”tcp”, ”server:9876”) if err != nil {

    panic(err) } , err := conn.Write(command1) if err != nil { panic(err) }
  3. conn, err := net.Dial(”tcp”, ”server:9876”) if err != nil {

    panic(err) } , err := conn.Write(command1) if err != nil { panic(err) } r := bufio.NewReader(conn) status := r.ReadString(’\n’)
  4. conn, err := net.Dial(”tcp”, ”server:9876”) if err != nil {

    panic(err) } , err := conn.Write(command1) if err != nil { panic(err) } r := bufio.NewReader(conn) status, err := r.ReadString(’\n’)
  5. conn, err := net.Dial(”tcp”, ”server:9876”) if err != nil {

    panic(err) } , err := conn.Write(command1) if err != nil { panic(err) } r := bufio.NewReader(conn) status, err := r.ReadString(’\n’) if err != nil { panic(err) }
  6. conn, err := net.Dial(”tcp”, ”server:9876”) if err != nil {

    panic(err) } , err := conn.Write(command1) if err != nil { panic(err) } r := bufio.NewReader(conn) status, err := r.ReadString(’\n’) if err != nil { panic(err) } if status == ”ok” { conn.Write(command2) }
  7. conn, err := net.Dial(”tcp”, ”server:9876”) if err != nil {

    panic(err) } , err := conn.Write(command1) if err != nil { panic(err) } r := bufio.NewReader(conn) status, err := r.ReadString(’\n’) if err != nil { panic(err) } if status == ”ok” { , err := conn.Write(command2) if err != nil { panic(err) } }
  8. conn := net.Dial(”tcp”, ”server:9876”) conn.Write(command1) r := bufio.NewReader(conn) status :=

    r.ReadString(’\n’) if status == ”ok” { conn.Write(command2) }
  9. conn := net.Dial(”tcp”, ”server:9876”) conn.Write(command1) r := bufio.NewReader(conn) status :=

    r.ReadString(’\n’) if status == ”ok” { conn.Write(command2) } if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil if err != nil
  10. conn.Write(command1) Not really the network An abstraction A value .

    . . containing data about the connection . . . and behaviour to use it
  11. A value . . . containing data about the connection

    . . . and behaviour to use it Determined by the type
  12. func (c ∗SafeConn) write(b []byte) { if c.err != nil

    { return } , c.err := c.Write(b) }
  13. c := SafeConn{conn, nil} c.write(command1) // if this has an

    error c.write(command2) // then this does nothing
  14. c := SafeConn{conn, nil} c.write(command1) // if this has an

    error c.write(command2) // then this does nothing if c.err != nil { panic(”omg”) }
  15. c := safeDial(”tcp”, ”server:9876”) // if this fails c.write(command1) //

    then this does nothing c.write(command2) if err != nil { panic(”give”) }
  16. c := safeDial(”tcp”, ”server:9876”) // if this fails c.write(command1) //

    then this does nothing c.write(command2) // same for this if err != nil { panic(”you”) }
  17. func divide(a, b, c int ) { answer := a

    / b / c fmt. Println (answer) }
  18. func divide(a, b, c int ) { answer := a

    / b / c fmt. Println (answer) } ... divide(100, 10, 2) // 5
  19. func divide(a, b, c int ) { answer := a

    / b / c fmt. Println (answer) } ... divide(100, 10, 0)
  20. func divide(a, b, c int ) { answer := a

    / b / c fmt. Println (answer) } ... divide(100, 10, 0) // panic: runtime error: integer divide by zero
  21. func divide(a, b, c int ) { answer := a

    / b / c fmt. Println (answer) } ... divide(100, 10, 0) // Can’t divide by zero
  22. func divide(a, b, c int ) { if b ==

    0 || c == 0 { fmt. Printf (”Can’t divide by zero”) return } answer = a / b / c fmt. Println (answer) }
  23. func divide(a, b, c int ) { answer := a

    / b / c fmt. Println (answer) }
  24. func divide(a, b, c int ) { answer := a

    / b / c fmt. Println (answer) } if b == 0 if b == 0 return if c == 0 if c == 0 if b == 0 if c == 0 if b == 0 if b == 0 if c == 0 if c == 0 if b == 0 return return
  25. Create a new type Wrap the initial value Wrap the

    behaviour Wrap the conditionals
  26. func (d ∗Divideinator) divide(x int ) { if x ==

    0 { d.isZero = true return } d.answer = d.answer / x }
  27. func (d Divideinator) String () string { if d.isZero {

    return fmt. Sprintf (”Can’t divide by zero”) } return fmt. Sprintf (”%d”, d.answer) }
  28. func divide(a, b, c int ) { d := Divideinator{a}

    d.divide(b) d.divide(c) fmt. Println (d) }
  29. func divide(a, b, c int ) { d := Divideinator{a}

    d.divide(b) d.divide(c) fmt. Println (d) } ... divide(100, 10, 2) // 5
  30. func divide(a, b, c int ) { d := Divideinator{a}

    d.divide(b) d.divide(c) fmt. Println (d) } ... divide(100, 0, 2) // Can’t divide by zero
  31. func divide(a, b, c int ) { d := Divideinator{a}

    d.divide(b) d.divide(c) fmt. Println (d) } ... divide(100, 10, 0) // Can’t divide by zero
  32. Create a new type Wrap the initial value Wrap the

    behaviour Wrap the conditional
  33. D(100) D( ) D( ) 100 10 5 divide(x) ;

    divide(y) divide(0) divide(0) /10 /0 Divideinator /2 /0
  34. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) validateEmail(email)

    checkAlreadyRegistered(email) register (email) sellEmailToRecruiters(email) }
  35. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) validateEmail(email)

    checkAlreadyRegistered(email) register (email) sellEmailToRecruiters(email) logRequest(r) }
  36. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) validateEmail(email)

    checkAlreadyRegistered(email) register (email) sellEmailToRecruiters(email) logRequest(r) fmt. Fprintln (w, ...) }
  37. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) if

    !validateEmail(email) { http .Error(w, ...) return } checkAlreadyRegistered(email) register (email) sellEmailToRecruiters(email) logRequest(r) fmt. Fprintln (w, ...) }
  38. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) if

    !validateEmail(email) { logRequest(”invalid email”, r) http .Error(w, ...) return } checkAlreadyRegistered(email) register (email) sellEmailToRecruiters(email) logRequest(r) fmt. Fprintln (w, ...) }
  39. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) if

    !validateEmail(email) { logRequest(”invalid email”, r) http .Error(w, ...) return } if alreadyRegistered(email) { logRequest(”already registered”, r) http .Error(w, ...) return } register (email) sellEmailToRecruiters(email) logRequest(r) fmt. Fprintln (w, ...) }
  40. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) if

    !validateEmail(email) { logRequest(”invalid email”, r) http .Error(w, ...) return } if alreadyRegistered(email) { sellEmailToRecruiters(email) logRequest(”already registered”, r) http .Error(w, ...) return } register (email) sellEmailToRecruiters(email) logRequest(r) fmt. Fprintln (w, ...) }
  41. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) if

    !validateEmail(email) { logRequest(”invalid email”, r) http .Error(w, ...) return } if alreadyRegistered(email) { sellEmailToRecruiters(email) logRequest(”already registered”, r) http .Error(w, ...) return } if err := register (email); err != nil { sellEmailToRecruiters(email) logRequest(”registration failed ”, r) http .Error(w, ...) return }
  42. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) validateEmail(email)

    checkAlreadyRegistered(email) register (email) sellEmailToRecruiters(email) logRequest(r) fmt. Fprintln (w, ...) }
  43. func signupHandler(w http.ResponseWriter, r ∗http.Request) { email := r.FormValue(”email”) validateEmail(email)

    checkAlreadyRegistered(email) register (email) sellEmailToRecruiters(email) logRequest(r) fmt. Fprintln (w, ...) } if err != nil if alreadyRegistered logRequest if err != nil if !validateEmail logRequest if alreadyRegistered if err != nil sellEmail logRequest
  44. Ta Tb Tc Td Te a b c d e

    λ Tf Tf() ; Tg() ; Th() ; Ti() Tg Th Ti f g h i
  45. Ta Tb Tc Td Te a b c d e

    λ Tf Tf() ; Tg() ; Th() ; Ti() Tg Th Ti f g h i
  46. Ta Tb Tc Td Te a b c d e

    λ Tf Tf() ; Tg() ; Th() ; Ti() Tg Th Ti f g h i
  47. Ta Tb Tc Td Te a b c d e

    λ Tf Tf() ; Tg() ; Th() ; Ti() Tg Th Ti f T g h i
  48. Ta Tb Tc Td Te a b c d e

    λ Tf Tf() ; Tg() ; Th() ; Ti() Tg Th Ti f T T g T h T i T
  49. Ta Tb Tc Td Te a b c d e

    λ Tf Tf() ; Tg() ; Th() ; Ti() Tg Th Ti f T T g T h T i T T T T T
  50. func (s ∗SignupRequest) checkNewRegistration() { if s.err != nil {

    return } if existingEmails.Contain(s.email) { s.err = ”already registered” } }
  51. func signupHandler(w http.ResponseWriter, r ∗http.Request) { s := newSignupRequest(w, r)

    s.validate () s.checkNewRegistration() s. register () s.sellEmailToRecruiter() }
  52. func signupHandler(w http.ResponseWriter, r ∗http.Request) { s := newSignupRequest(w, r)

    s.validate () s.checkNewRegistration() s. register () s.sellEmailToRecruiter() s.log() }
  53. func signupHandler(w http.ResponseWriter, r ∗http.Request) { s := newSignupRequest(w, r)

    s.validate () s.checkNewRegistration() s. register () s.sellEmailToRecruiter() s.log() s.respond() }
  54. . . . but then we need to join the

    pieces back together again
  55. Thank you John Cinnamond dotGo 2017 Gophers adapted from The

    Go Gopher by Renee French https://blog.golang.org/gopher