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

Avatar for John Cinnamond

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