Boston Elixir
Presented by Jean-François Cloutier
At the Boston Elixir Meetup
March 15, 2016
Building a robot dashboard with Phoenix and Elm
Boston Elixir
See Marv
Infrared sensor (to sense beacon
distance and direction)
Touch sensor(to detect collisions)
Large motors(to move and turn)
Medium motor (turned on when
“eating”)
LEDs(green when moving around, orange when finding food, red
when panicking)
Color sensor (to see the “food”)
Beacon(to simulate the smell of food)
Ultrasonic sensor (to sense
proximity of obstacles)
Speaker(to emote)
Powered by elixir
Boston Elixir
The blue paper is food.
The beacon above it emits the scent of food.
Marv is curious and likes to roam around.
But when he is hungry, he forages for food instead.
Unless he is scared. Then he panics and runs around like a headless chicken.
What Marv is saying:
“I am hungry”
“Uh oh” (when colliding)
“I am stuck”
“I am scared”
“Nom de nom de nom” (when eating)
See Marv run
Boston Elixir
https://www.youtube.com/watch?v=NbquttnKuak
See Marv run
Boston Elixir
Marvin Minsky1927-2016
The society of mind theory views the human mind and any other naturally evolved cognitive systems as a vast society of individually simple processes known as agents. These processes are the fundamental thinking entities from which minds are built, and together produce the many abilities we attribute to minds.
Minds are what brains do
https://en.wikipedia.org/wiki/Society_of_Mind
The great power in viewing a mind as a society of agents, as opposed to the consequence of some basic principle or some simple formal system, is that different agents can be based on different types of processes with different purposes, ways of representing knowledge, and methods for producing results.
Boston Elixir A (simple) society of agents
Boston Elixir
Hunger
On track
Food
Started
Foraging behavior
Off track
Feeding
Scentstrength
Scentdirection
Scentdirection
Scentstrength
Food
Colliding(reflex)
Gettingunstuck(reflex)
Stuck Collision
Boston Elixir
Detector, Internal clock
Detector, Internal clock
PerceptorPerceptor
MotivatorMotivator
BehaviorBehavior
ActuatorActuatorActions cause measures to change
Agents create and react to percepts, motives and intents concurrently
Agents interact indirectly via events dispatched by the CNS, and via the short-term memories they create and retrieve
From these concurrent and indirect interactions, we get a (lively) mess of transient, entangled control loops
All together now
Boston ElixirMarv's mind map
Boston Elixir
The urgency of now
A robot must deal with the “here and now”
• It can't afford to react to its situation as it was seconds ago
When the robot is falling behind, it sees increasingly stale percepts, motives or intents
• At some point, they become dangerously out-of-sync with reality
One solution
• Ignore stale percepts, motives and intents● Strong intents take longer to become stale
• And make the robot faint (briefly)● CNS temporarily stops the production of Percepts by Detectors
and by the Internal Clock
● Giving the robot a chance to catch up
Boston Elixir
A dashboard you said?
Clearly, what goes on in the robot's mind is complex:
• A constant flood of percepts
• Turns motives on and off
• Triggering and halting behaviors
• Each driven by percepts
• And generating intents on state transitions
All of which happens all the time, at the same time
I wanted a dashboard so I could peek into the mind of my robot
Boston Elixir
The robot dashboard
Pause/resume robot
The robot fainted
Latest value for each type of percepts
Current memory usage
Status of all motives
Green is on, red is off
Strike-through when inhibited
Current state of all behaviors
Green is triggered, red is terminated, yellow is
overwhelmedStrike-through when
inhibitedReflexes are in italics
Latest values of all realized intents
Boston Elixir
Reading the dashboard
Boston Elixir
Elmruntime
Under the dashboard
Router
Channel
CNS
ChannelsHandler
events
events
Web sockets (JSON)
View
HTTP
(Rest) Controller
App
UpdateUpdate
ModelModel
ViewView
signals
signals
Elixir/OTP
Phoenix
TaskPorttasks
On the browser On the robot
PortPort
Boston Elixir
About
Elm is a functional programming language for the browser
• Elm transpiles to Javascript
• Intelligently typed
• Pure functions
Elm is reactive
• Signals in and signals out
• Actions modify the model which modifies the virtual DOM
● The real DOM is then automatically and minimally updated
● No cyclical side-effect cascades or other horrors
Elm is a many-splendored thing
• Very declarative, very fast
• Marvelously informative compiler errors
• If it compiles, you know you won't see runtime errors
From http://staltz.com/unidirectional-user-interface-architectures.html
Boston Elixir
Elm is small
Few concepts to master:
• Data● Numbers, strings, lists, tuples, records
• Functions● Named or anonymous
• Types● Implied or declared, composable, and never
ambiguous
• Signals● Time-varying values (reactivity!)
• Tasks● Deferred execution of functions
• Modules● To organize, hide and expose functions and types
• Ports● Sanitary access to and from the dirty, side-effect-
ridden outside worldSee http://elm-lang.org/docs/syntax
Boston Elixir
Elm is functional
All functions all the time
Functions can be curried
Functions can operate on functions
• Mapping, filtering, folding...
From http://package.elm-lang.org/packages/elm-lang/core/3.0.0/List
List
From https://dennisreimann.de/articles/elm-functions.html
Boston Elixir
Elm runtime (JS)
Elm is
Functions can not cause side-effects “within” Elm
• All side-effects happen “outside”
● In the Elm runtime
• As outgoing Tasks● Delayed executions
of functions
• Or as incoming Signals of Actions
● “To-do's” for updating the model
Elm app
updatefunction
port
immutablemodel
viewfunction
task
Causing side-effects:REST calls,
DB updates etc.
Signals
Strictlyfunctional
Reporting side-effects:
Socket pushes,user interactions...
Boston Elixir
Elm is reactive
With signals, time becomes a 1st class citizen
• A signal is a stream of values representing a state changing over time (e.g. the position of the mouse)
The application reacts to multiple signals by...
• Constantly re-calculating from merged signals the aggregate state, from time zero to now
• Producing a signal of views on that aggregate state, causing display refreshes
• Creating signals of tasks (think JS
promises) that, when executed, cause external state changes (e.g. DB updates, REST calls etc.)
From http://www.elm-tutorial.org/effects/tasks.html
From http://elm-lang.org/guide/reactivity
Boston Elixir
Elm is friendly
Excellent tooling
• REPL
• Build tool plugins (brunch, grunt...)
• Code editor support
• Easy install (nmp install ...)
World's best compiler error messages
No runtime errors. Evah!
Boston Elixir
Integrating Elm and Phoenix
Elm is embedded in the Phoenix application
And integrated in the build (and automatic rebuild) process
• See package.json, brunch-config.js
Phoenix
RobotDashboard.js RobotDashboard.elmapp.js
brunch build
Adapted from http://www.cultivatehq.com/posts/phoenix-elm-2/
Boston Elixir
Composing the dashboard
AppStatus
Perception
Motivation
Comportment Actuation
Boston Elixir
Organizing the code
RobotDashboard.elm (the main module)
• StartApp (“main”), input signals and ports
The app module (under App) and component modules (under Status, Perception, Motivation, Comportment and Actuation)
• Model● The model types and functions for instantiation,
initialization
• Update● The update action types and the model update
functions
• View● The HTML generation functions
App structure and framework modeled after Elm-Hedley
Boston Elixir
Model
Each component defines a model as a record
The payloads of signals from Phoenix are also records Status/Model.elm
Boston Elixir
Model
The overall model is a record of the components' model records
App/Model.elm
Boston Elixir
Updating
Actions are defined as union types
The update function responds to actions (carried by
signals) by
• transforming the model
• and potentially creating new actions as effects
Status/Update.elm
Boston Elixir
Updating
The App's update function
• Receives all actions
• “Peels” and dispatches each action to its target component
App/Update.elm
Boston Elixir
Views
Views generate the HTML that presents the current state of the model
And sets up user triggered actions as effects
Status/View.elm
Boston Elixir
Views
The App view function displays the entire dashboard
• by delegating to the view function of each component
• and wrapping each component's “address” with its own distinguishing action tag
App/View.elm
Boston Elixir
Elm runtime
Elixir/OTP
Elm queries Phoenix
Via a REST API
• Configured in Ev3.Router
• /robot/togglePaused (post)● Toggles the robot between
fainting and reviving
● Delegated to Ev3.RobotController
● Who sends a “toggle_paused” event to the CNS
• /robot/paused (get)● Ev3.RobotController asks the
CNS
● About the fainted vs. revived status of the robot
Elm
PhoenixEndpoint
Router
RobotController
CNS
Dashboard
Task
Boston Elixir
Phoenix signals Elm
A Phoenix channel (RobotChannel) is joined by the Dashboard
CNS dispatches event notifications to its event handlers
• ChannelsHandler is one of the event handlers
• It converts events of interest into broadcasts to the channel the Dashboard has joined
Boston Elixir
Elm runtime
Phoenix signals Elm
The main Elm module (RobotDashboard) defines ports for incoming signals
• Each port specifies a signal of a given type
Each kind of Phoenix channel event (broadcasted from ChannelsHandler) is associated (in app.js) with an Elm port
• There's an event for reporting fainting, another event for new percepts, new motives etc.
• The payload of a broadcasted event must match the Elm data type of the targeted Elm port
• Data format translation (Elixir map to
JSON to Elm record) is automatic
Elixir/OTP
Elm
PhoenixUserSocket
RobotChannel
ChannelsHandler
CNS
Dashboard
Port
Boston Elixir
Loving it!
Phoenix + Elm > peanut butter + jam
Elm changed the way I think about code
● Functional Reactive Programming● Strict (but smart) typing● Side-effect-free coding● No runtime errors
At first, the Elm Architecture felt like a strange way of doing Web apps
● Signals, tasks, effects and ports● JSON decoding● UI as a signal of HTML
But now I am hooked
Boston Elixir
And it's about to get even better
March 11, 2016 – Erlang Factory SF
Chris McCord (Phoenix) and Evan Czaplicki (Elm) announced they will collaborate to better integrate Phoenix and Elm
Chris
Evan
https://www.youtube.com/watch?v=XJ9ckqCMiKk
Boston Elixir
Resources for
Elm
• elm-lang.org
• elm-tutorial.org
• The Pragmatic Studio online courses● Elm: Building Reactive Web Apps
● Elm: Signals, Mailboxes & Ports
Phoenix
• phoenixframework.org
• Programming Phoenix (book)
Elm-Phoenix integration
• Cultivate's blog series
• Phoenix channels doc
+
Boston Elixir
I blog about all this
http://jfcloutier.github.io/robotex/
Boston Elixir
Next steps
Two robots!
• Sharing perceptions, spreading motives, influencing behaviors
• How do societies of mind form a society of minds?
Moving to Nerves Project + ev3dev
• Smaller memory footprint for running Elixir (and Phoenix) on the EV3
• Coming soon
Boston Elixir
Thank you all!
I organize the Portland (Maine) Erlang & Elixir meetup
• Twitter: jfcloutier
• Github: https://github.com/jfcloutier/ev3