File tree Expand file tree Collapse file tree 2 files changed +42
-1
lines changed Expand file tree Collapse file tree 2 files changed +42
-1
lines changed Original file line number Diff line number Diff line change @@ -53,6 +53,9 @@ to understand and maintain.
53
53
module Control.Monad.Cont (
54
54
-- * MonadCont class
55
55
MonadCont. MonadCont (.. ),
56
+ MonadCont. label ,
57
+ MonadCont. label_ ,
58
+
56
59
-- * The Cont monad
57
60
Cont. Cont ,
58
61
Cont. cont ,
@@ -71,9 +74,12 @@ module Control.Monad.Cont (
71
74
72
75
-- * Example 2: Using @callCC@
73
76
-- $callCCExample
74
-
77
+
75
78
-- * Example 3: Using @ContT@ Monad Transformer
76
79
-- $ContTExample
80
+
81
+ -- * Example 4: Using @label@
82
+ -- $labelExample
77
83
) where
78
84
79
85
import qualified Control.Monad.Cont.Class as MonadCont
@@ -165,3 +171,19 @@ and passes it to the continuation.
165
171
and returning @IO ()@.
166
172
Compare its signature to 'runContT' definition.
167
173
-}
174
+
175
+ {- $labelExample
176
+
177
+ The early exit behavior of 'Control.Monad.Cont.Class.callCC' can be leveraged to produce other idioms:
178
+
179
+ > whatsYourNameLabel :: IO ()
180
+ > whatsYourNameLabel = evalContT $ do
181
+ > (beginning, attempts) <- label (0 :: Int)
182
+ > liftIO $ putStrLn $ "Attempt #" <> show attempts
183
+ > liftIO $ putStrLn $ "What's your name?"
184
+ > name <- liftIO getLine
185
+ > when (null name) $ beginning (attempts + 1)
186
+ > liftIO $ putStrLn $ "Welcome, " ++ name ++ "!"
187
+
188
+ Calling @beggining@ will interrupt execution of the block, skipping the welcome message, which will be printed only once at the very end of the loop.
189
+ -}
Original file line number Diff line number Diff line change @@ -56,8 +56,11 @@ to understand and maintain.
56
56
57
57
module Control.Monad.Cont.Class (
58
58
MonadCont (.. ),
59
+ label ,
60
+ label_ ,
59
61
) where
60
62
63
+ import Control.Monad.Fix (fix )
61
64
import Control.Monad.Trans.Cont (ContT )
62
65
import qualified Control.Monad.Trans.Cont as ContT
63
66
import Control.Monad.Trans.Except (ExceptT )
@@ -152,3 +155,19 @@ instance
152
155
, MonadCont m
153
156
) => MonadCont (AccumT w m ) where
154
157
callCC = Accum. liftCallCC callCC
158
+
159
+ -- | Introduces a recursive binding to the continuation.
160
+ -- Due to the use of @callCC@, calling the continuation will interrupt execution
161
+ -- of the current block creating an effect similar to goto/setjmp in C.
162
+ --
163
+ -- @since 2.3.1
164
+ --
165
+ label :: MonadCont m => a -> m (a -> m b , a )
166
+ label a = callCC $ \ k -> let go b = k (go, b) in return (go, a)
167
+
168
+ -- | Simplified version of `label` without arguments
169
+ --
170
+ -- @since 2.3.1
171
+ --
172
+ label_ :: MonadCont m => m (m a )
173
+ label_ = callCC $ return . fix
You can’t perform that action at this time.
0 commit comments