[Haskell-cafe] Pesky monads...

2007-05-19 Thread Andrew Coppin
I've been getting some pretty weird complaints from the type checker. 
And I just figured out why! Grr...


Is there any function that does the same thing as until, but in a monad?

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Pesky monads...

2007-05-19 Thread Matthew Cox
You can define one:

untilM :: Monad m = (a - Bool) - (a - m a) - a - m a
untilM pred f x | pred x = return x
| otherwise = f x = untilM pred f

Matthew Cox

- Original Message -
From: Andrew Coppin
To:  haskell-cafe@haskell.org
Sent:  Sat, 19 May 2007 19:49:40 +0100
Subject: [Haskell-cafe] Pesky monads...

I've been getting some pretty weird complaints from the type checker. 
And I just figured out why! Grr...

Is there any function that does the same thing as until, but in a monad?

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Pesky monads...

2007-05-19 Thread Andrew Coppin

Matthew Cox wrote:

You can define one:

untilM :: Monad m = (a - Bool) - (a - m a) - a - m a
untilM pred f x | pred x = return x
| otherwise = f x = untilM pred f

Matthew Cox
  

Hey, neat! :-D

Mmm, I wonder if one could use fail to exit the loop instead... Oh, 
wait, for some monads that fires an error. Hmm. Nice try.


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Pesky monads...

2007-05-19 Thread Matthew Cox
It occurred to me that the predicate will generally be a monadic function 
itself, so here's a
refined version:

 :: Monad m = (a - m Bool) - (a - m a) - a - m a
untilM pred f x = do c - pred x
 if c then return x
  else f x = untilM pred f

Think of a computation in the State monad, a predicate will probably want to 
consult that state.

Matthew Cox

- Original Message -
From: Matthew Cox
To:  haskell-cafe@haskell.org
Sent:  Sat, 19 May 2007 13:10:40 -0600
Subject: Re: [Haskell-cafe] Pesky monads...

You can define one:

untilM :: Monad m = (a - Bool) - (a - m a) - a - m a
untilM pred f x | pred x = return x
| otherwise = f x = untilM pred f

Matthew Cox

- Original Message -
From: Andrew Coppin
To:  haskell-cafe@haskell.org
Sent:  Sat, 19 May 2007 19:49:40 +0100
Subject: [Haskell-cafe] Pesky monads...

I've been getting some pretty weird complaints from the type checker. 
And I just figured out why! Grr...

Is there any function that does the same thing as until, but in a monad?

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Pesky monads...

2007-05-19 Thread haskell
I previously worked out how to use the monad transformers to make a when /
repeat control structure that admitted both break and continue
statements.  It uses a ContT monad transformer to provide the escape semantics
and the Reader to store the continuation.

I'll paste the code here:

 -- By Chris Kuklewicz, BSD-3 license, February 2007
 -- Example of pure while and repeat until looping constucts using
 -- the monad transformer library.  Works for me in GHC 6.6
 --
 -- The underscore version is ContT of RWS and this works more
 -- correctly than the non-underscore version of RWST of Cont.
 --
 -- Perhaps Monad Cont done right from the wiki would help?
 import Control.Monad.Cont
 import Control.Monad.RWS
 import Control.Monad.Error
 import Control.Monad.ST
 import System.IO.Unsafe
 import Data.STRef
 
 -- Note that all run* values are the same Type
 main = mapM_ print [run,run2,run_,run2_]
 
 run,run_,run2,run2_ :: MyRet ()
 run = runner testWhile
 run2 = runner testRepeatUntil
 run_ = runner_ testWhile_
 run2_ = runner_ testRepeatUntil_
 
 -- runner_ uses ContT RWS to provide better semantics when break is called
 -- runner_ :: (Monad (RWS (Exit_ r a1 b) w Int)) = ContT a (RWS (Exit_ r a1 
 b) w Int) a - (a, Int, w)
 runner_ m = runRWS (runContT m return) NoExit_ (17::Int)
 
 -- runner uses RWST Cont and does not work as desired
 -- runner :: (Num s) = RWST (Exit r a1 b) w s (Cont (a, s, w)) a - (a, s, w)
 runner m = (flip runCont) id (runRWST m NoExit (17))
 
 testRepeatUntil_ = repeatUntil_ (liftM (==17) get) innerRepeatUntil_
 testRepeatUntil = repeatUntil (liftM (==17) get) innerRepeatUntil
 
 innerRepeatUntil_ = tell_ [I ran]  breakW_
 innerRepeatUntil = tell [I ran]  breakW
 
 testWhile_ = while_ (liftM (10) get) innerWhile_
 testWhile = while (liftM (10) get) innerWhile
 
 -- innerWhile_ :: ContT () (T_ (Exit_ () Bool Bool)) ()
 innerWhile_ = do
   v - get
   tell_ [show v]
   when' (v==20) (tell_ [breaking]  breakW_)
   if v == 15 
 then put 30  continueW_
 else modify pred
 
 innerWhile = do
   v - get
   tell [show v]
   when' (v==20) (tell [breaking]  breakW)
   if v == 15 
 then put 30  continueW
 else modify pred
 
 -- The Monoid restictions means I can't write an instance, so use tell_
 tell_ = lift . tell
 
 -- Generic defintions
 getCC :: MonadCont m = m (m a)
 getCC = callCC (\c - let x = c x in return x)
 getCC' :: MonadCont m = a - m (a, a - m b)
 getCC' x0 = callCC (\c - let f x = c (x, f) in return (x0, f))
 
 when' :: (Monad m) = Bool - m a - m ()
 when' b m = if b then (m  return ()) else return ()
 
 -- Common types
 type MyState = Int
 type MyWriter = [String]
 type MyRet a = (a,MyState,MyWriter)
 -- RWST of Cont Types
 type T r = RWST r MyWriter MyState
 type Foo r a = T (Exit (MyRet r) a a) (Cont (MyRet r))
 type WhileFunc = Foo () Bool
 type ExitFoo r a = Foo r a a --  (Exit r a a)  (Cont r) a
 type ExitType r a = T (Exit r a a)  (Cont r) a
 data Exit r a b = Exit (a - ExitType r b) | NoExit
 -- ContT of RWS Types
 type T_ r = RWS r MyWriter MyState
 type ExitType_ r a = ContT r (T_ (Exit_ r a a)) a
 data Exit_ r a b = Exit_ (a - ExitType_ r b) | NoExit_
 
 -- Smart destructor for Exit* types
 getExit (Exit loop) = loop
 getExit NoExit = (\ _ - return (error NoExit))
 getExit_ (Exit_ loop) = loop
 getExit_ NoExit_ = (\ _ - return (error NoExit))
 
 -- The with* functions here use the Reader monad features to scope the
 -- break and continue commands.
 
 -- I cannot see how to lift withRWS, so use local
 -- Perhaps Monad Cont done right from the wiki would help?
 withLoop_ loop = local (\r - Exit_ loop)
 -- withRWST can change the reader Type
 withLoop loop = withRWST (\r s - (Exit loop,s)) 
 
 -- The condition is never run in the scope of the (withLoop loop)
 -- continuation.  I could have invoked (loop True) for normal looping
 -- but I decided a tail call works as well.  This decision has
 -- implication for the non-underscore version, since the writer/state
 -- can get lost if you call (loop _).
 while_ mCondition mBody = do
   (proceed,loop) - getCC' True
   -- break and continue jump here with new 'proceed' value
   let go = do check - mCondition
   when' check (withLoop_ loop mBody  go)
   when' proceed go
 
 while mCondition mBody = do
   (proceed,loop) - getCC' True
   -- break and continue jump here with new 'proceed' value
   let go = do check - mCondition
   when' check (withLoop loop mBody  go)
   when' proceed go
 
 repeatUntil_ mCondition mBody = do
   (proceed,loop) - getCC' True
   -- break and continue jump here with new 'proceed' value
   let go = do withLoop_ loop mBody
   check - mCondition
   when' (not check) go
   when' proceed go
 
 repeatUntil mCondition mBody = do
   (proceed,loop) - getCC' True
   -- break and continue jump here with new 'proceed' value
   let go = do withLoop loop mBody
   check - mCondition
   when' (not check) go
   when' proceed go
 
 -- The 

Re: [Haskell-cafe] Pesky monads...

2007-05-19 Thread Donald Bruce Stewart
matt:
 It occurred to me that the predicate will generally be a monadic function 
 itself, so here's a
 refined version:
 
  :: Monad m = (a - m Bool) - (a - m a) - a - m a
 untilM pred f x = do c - pred x
  if c then return x
   else f x = untilM pred f

Here's a cute example of a loop from xmonad:

fix $ \again - do
more - checkMaskEvent d enterWindowMask p
when more again 

But maybe Spencer was just being funny when he wrote that.

-- Don
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe