Skip to content

Instantly share code, notes, and snippets.

@Horusiath
Created November 4, 2016 08:10
Show Gist options
  • Save Horusiath/69f0521e74f713a4c81891333ea35131 to your computer and use it in GitHub Desktop.
Save Horusiath/69f0521e74f713a4c81891333ea35131 to your computer and use it in GitHub Desktop.
Free like a monad
type Distance = float
type Angle = float
type PenColor = string
type TurtleProgram =
// (input params) (response)
| Stop
| Move of Distance * TurtleProgram
| Turn of Angle * TurtleProgram
| PenUp of (* none *) TurtleProgram
| PenDown of (* none *) TurtleProgram
| SetColor of PenColor * TurtleProgram
type TurtleState =
{ color: PenColor; isDrawing: bool }
let rec interpret state program =
match program with
| Stop ->
state
| Move (dist,next) ->
reduceMoves dist state next
| Turn (angle,next) ->
reduceTurns angle state next
| PenUp next ->
let newState = { state with isDrawing = false }
interpret newState next
| PenDown next ->
let newState = { state with isDrawing = true }
interpret newState next
| SetColor (color,next) ->
let newState = { state with color = color }
interpret newState next
and reduceMoves acc state program =
match program with
| Move(dist, next) ->
// combine subsequent moves
reduceMoves (acc+dist) state next
| _ ->
if state.isDrawing then
printfn "Turtle drawn line: distance=%f, color=%s" acc state.color
else
printfn "Turtle moved: distance=%f" acc
interpret state program
and reduceTurns acc state program =
match program with
| Turn(angle, next) ->
// combine subsequent turns
reduceTurns (acc+angle) state next
| _ ->
printfn "Turtle turned %f degrees" acc
interpret state program
let drawTriangle =
Move(100.0,
Turn(120.0,
Move(50., // those two moves will be folded
Move(50.,
Turn(120.0,
Move(100.,
Turn(120.0,
Stop)))))))
interpret {isDrawing = true; color = "Blue" } drawTriangle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment