Skip to content

Commit c465ddc

Browse files
committed
Continuation Monad no longer used. Now uses Exception Monad which frees up some type constraints.
1 parent 7e51c47 commit c465ddc

File tree

5 files changed

+135
-150
lines changed

5 files changed

+135
-150
lines changed

worldturtle/Graphics/WorldTurtle.hs

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ import qualified Graphics.Gloss.Interface.Pure.Game as G
4949
import Graphics.WorldTurtle.Color
5050
import Graphics.WorldTurtle.Commands
5151
import Graphics.WorldTurtle.Internal.Sequence (renderTurtle)
52-
import Graphics.WorldTurtle.Internal.Commands (TurtleCommand, seqT
53-
, WorldCommand (..), seqW)
52+
import Graphics.WorldTurtle.Internal.Commands ( TurtleCommand
53+
, WorldCommand (..), seqW
54+
, run)
5455
import Graphics.WorldTurtle.Shapes
5556

5657
-- | Takes a `TurtleCommand` and executes the command on an implicitly created
@@ -108,26 +109,6 @@ runWorld tc = G.play display white 30 defaultWorld iterateRender input timePass
108109
| running w = w { elapsedTime = f + elapsedTime w }
109110
| otherwise = w
110111

111-
-- | `run` takes a `TurtleCommand` and a `Turtle` to execute the command on.
112-
-- The result of the computation is returned wrapped in a `WorldCommand`.
113-
--
114-
-- For example, to create a turtle and get its @x@ `position` one might
115-
-- write:
116-
--
117-
-- > myCommand :: Turtle -> WorldCommand Float
118-
-- > myCommand t = do
119-
-- > (x, _) <- run position t
120-
-- > return x
121-
--
122-
-- Or to create a command that accepts a turtle and draws a right angle:
123-
--
124-
-- > myCommand :: Turtle -> WorldCommand ()
125-
-- > myCommand = run $ forward 10 >> right 90 >> forward 10
126-
run :: TurtleCommand a -- ^ Command to execute
127-
-> Turtle -- ^ Turtle to apply the command upon.
128-
-> WorldCommand a -- ^ Result as a `WorldCommand`
129-
run c = WorldCommand . seqT c
130-
131112
-- | This is an infix version of `run` where the arguments are swapped.
132113
--
133114
-- We take a turtle and a command to execute on the turtle.

worldturtle/Graphics/WorldTurtle/Commands.hs

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ module Graphics.WorldTurtle.Commands
4545
, setRotationSpeed
4646
-- * Styling commands.
4747
, stamp
48+
, representation
4849
-- ** Query turtle's state.
4950
, position
5051
, heading
@@ -53,7 +54,6 @@ module Graphics.WorldTurtle.Commands
5354
, penColor
5455
, penDown
5556
, penSize
56-
, representation
5757
, visible
5858
-- ** Mutate turtle's state.
5959
, branch
@@ -90,24 +90,29 @@ import Graphics.Gloss.Data.Picture
9090
Creates a new `Turtle` and displays it on the canvas. This turtle can then be
9191
manipulated! For example, to create a turtle and then move the turtle forward:
9292
93-
> main:: IO ()
94-
> main = runWorld $ do
95-
> t <- makeTurtle
96-
> t >/> forward 90
93+
@
94+
main:: IO ()
95+
main = runWorld $ do
96+
t <- makeTurtle
97+
t >/> forward 90
98+
@
99+
100+
The default turtle starts at position (0, 0) and is orientated `north`.
97101
98-
The default turtle starts at position @(0, 0)@ and is orientated `north`.
99102
-}
100103
makeTurtle :: WorldCommand Turtle
101104
makeTurtle = WorldCommand generateTurtle
102105

103106
{-| This variant of `makeTurtle` takes a starting position, a starting
104107
orientation, and a color to apply to the turtle and the turtle's pen.
105108
106-
> myCommand :: WorldCommand ()
107-
> myCommand = do
108-
> t1 <- makeTurtle' (0, 0) 0 green
109-
> t2 <- makeTurtle' (0, 0) 90 red
110-
> t1 >/> forward 90 <|> t2 >/> forward 90
109+
@
110+
myCommand :: WorldCommand ()
111+
myCommand = do
112+
t1 <- makeTurtle' (0, 0) 0 green
113+
t2 <- makeTurtle' (0, 0) 90 red
114+
(t1 >/> forward 90) \<|\> (t2 >/> forward 90)
115+
@
111116
112117
See `makeTurtle`.
113118
-}
@@ -203,7 +208,7 @@ rotateTo_ rightBias !r = TurtleCommand $ \ turtle -> do
203208
turtLens_ turtle . T.heading .= newHeading
204209

205210
-- | Draw a circle with a given @radius@. The center is @radius@ units left of
206-
-- the turtle if positive. Otherwise @radius@ units right of the turtle
211+
-- the @turtle@ if positive. Otherwise @radius@ units right of the @turtle@
207212
-- if negative.
208213
--
209214
-- The circle is drawn in an anticlockwise direction if the radius is
@@ -244,7 +249,7 @@ calculateNewPointC_ !p !radius !startAngle !angle = (px, py)
244249
else startAngle - angle
245250

246251
-- | Draw an arc with a given @radius@. The center is @radius@ units left of the
247-
-- turtle if positive. Otherwise @radius@ units right of the turtle if
252+
-- @turtle@ if positive. Otherwise @radius@ units right of the @turtle@ if
248253
-- negative.
249254
--
250255
-- The arc is drawn in an anticlockwise direction if the radius is positive,
@@ -282,7 +287,7 @@ position :: TurtleCommand P.Point -- ^ Returned current point.
282287
position = getter_ (0, 0) T.position
283288

284289
-- | Warps the turtle to its starting position @(0, 0)@ and resets the
285-
-- orientation to `north` (@90@ degrees). No line is drawn moving the turtle.
290+
-- orientation to @North@ (90 degrees). No line is drawn moving the turtle.
286291
home :: TurtleCommand ()
287292
home = TurtleCommand $ \ turtle -> do
288293
let ts = turtLens_ turtle
@@ -373,7 +378,7 @@ setVisible = setter_ T.visible
373378

374379
-- | Returns the turtle's current speed.
375380
-- Speed is is @distance@ per second.
376-
-- A speed of @0@ is equivalent to no animation being performed and instant
381+
-- A speed of @0 is equivalent to no animation being performed and instant
377382
-- movement.
378383
-- The default value is @200@.
379384
speed :: TurtleCommand Float -- ^ Speed of turtle.
@@ -407,14 +412,16 @@ representation = getter_ blank T.representation
407412
See `representation`.
408413
For example, to set the turtle as a red circle:
409414
410-
> import Graphics.WorldTurtle
411-
> import qualified Graphics.Gloss.Data.Picture as G
412-
>
413-
> myCommand :: TurtleCommand ()
414-
> myCommand = do
415-
> setPenColor red
416-
> setRepresentation (G.color red $ G.circleSolid 10)
417-
> forward 90
415+
@
416+
import Graphics.WorldTurtle
417+
import qualified Graphics.Gloss.Data.Picture as G
418+
419+
myCommand :: TurtleCommand ()
420+
myCommand = do
421+
setPenColor red
422+
setRepresentation (G.color red $ G.circleSolid 10)
423+
forward 90
424+
@
418425
-}
419426
setRepresentation :: Picture -- ^ Picture to apply.
420427
-> TurtleCommand ()
@@ -427,7 +434,7 @@ clear = WorldCommand $ pics .= []
427434
-- | Sleep for a given amount of time in seconds. When sleeping no animation
428435
-- runs. A negative value will be clamped to @0@.
429436
sleep :: Float -> WorldCommand ()
430-
sleep = WorldCommand . decrementSimTime . max 0
437+
sleep = WorldCommand . (\t -> decrementSimTime t ()) . max 0
431438

432439
-- | Given a command, runs the command, then resets the turtle's state back to
433440
-- what the state was before the command was run.
@@ -463,8 +470,8 @@ south = 270
463470
turtLens_ :: Applicative f
464471
=> Turtle
465472
-> (T.TurtleData -> f T.TurtleData)
466-
-> TSC b
467-
-> f (TSC b)
473+
-> TSC
474+
-> f TSC
468475
turtLens_ t = turtles . ix t
469476
{-# INLINE turtLens_ #-}
470477

worldturtle/Graphics/WorldTurtle/Internal/Commands.hs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Graphics.WorldTurtle.Internal.Commands
33
( SeqC
44
, TurtleCommand (..)
55
, WorldCommand (..)
6+
, run
67
) where
78

89
import Control.Applicative
@@ -12,7 +13,7 @@ import Graphics.Gloss.Data.Picture (text)
1213

1314
import Graphics.WorldTurtle.Internal.Sequence
1415

15-
type SeqC a = SequenceCommand (AlmostVal ()) a
16+
type SeqC a = SequenceCommand () a
1617

1718
{-| A `TurtleCommand` represents an instruction to execute on a turtle.
1819
It could be as simple as "draw a line" or more complicated like
@@ -56,7 +57,7 @@ instance Monad TurtleCommand where
5657
instance MonadFail TurtleCommand where
5758
fail t = TurtleCommand $ \ _ -> do
5859
addPicture $ text t
59-
failSequence
60+
failSequence ()
6061

6162
{- | A `WorldCommand` represents an instruction that affects the entire
6263
animation canvas.
@@ -90,7 +91,7 @@ instance Monad WorldCommand where
9091
(WorldCommand a) >>= f = WorldCommand $ a >>= \s -> seqW (f s)
9192

9293
instance Alternative WorldCommand where
93-
empty = WorldCommand failSequence
94+
empty = WorldCommand $ failSequence ()
9495
(<|>) (WorldCommand a) (WorldCommand b) = WorldCommand $ alternateSequence a b
9596

9697
instance Semigroup a => Semigroup (WorldCommand a) where
@@ -101,4 +102,24 @@ instance MonadPlus WorldCommand
101102
instance MonadFail WorldCommand where
102103
fail t = WorldCommand $ do
103104
addPicture $ text t
104-
failSequence
105+
failSequence ()
106+
107+
-- | `run` takes a `TurtleCommand` and a `Turtle` to execute the command on.
108+
-- The result of the computation is returned wrapped in a `WorldCommand`.
109+
--
110+
-- For example, to create a turtle and get its @x@ `position` one might
111+
-- write:
112+
--
113+
-- > myCommand :: Turtle -> WorldCommand Float
114+
-- > myCommand t = do
115+
-- > (x, _) <- run position t
116+
-- > return x
117+
--
118+
-- Or to create a command that accepts a turtle and draws a right angle:
119+
--
120+
-- > myCommand :: Turtle -> WorldCommand ()
121+
-- > myCommand = run $ forward 10 >> right 90 >> forward 10
122+
run :: TurtleCommand a -- ^ Command to execute
123+
-> Turtle -- ^ Turtle to apply the command upon.
124+
-> WorldCommand a -- ^ Result as a `WorldCommand`
125+
run c = WorldCommand . seqT c

0 commit comments

Comments
 (0)