haskell - "takeWhile" within a list comprehension -


i have following:

[bla z|n<-[0..], let z = foo n, z < 42] 

the thing is, want list comprehension end z < 42 fails, if takewhile. know refactor bunch of filters , maps, more elegant list comprehension.

what elegant way combine list comprehensions , takewhile?

since list comprehensions not allow this, have hacked bit using monad comprehensions , defining custom monad. outcome of following works:

example :: [int] example = tolist [1000 + n                   | n <- fromlist [0..]                  , _ <- nonstopguard (n > 1)                  , let z = 10*n                  , _ <- stopguard (z < 42) ]  -- output: [1002,1003,1004] 

the above works normal list comprehension, has 2 different kinds of guard. nonstopguard works regular guard, except requiring bizarre syntax. stopguard instead more: become false, stops further choices in previous generators (such <-[0..]) considered.

the small library wrote shown below:

{-# language derivefunctor, monadcomprehensions #-} import control.monad import control.applicative  data f = f [a] bool   deriving (functor, show) 

the bool above stop bit, signaling must stop considering further choices.

instance applicative f pure = return; (<*>) = ap instance monad f    return x = f [x] false    f [] s      >>= _ = f [] s    f (x:xs) sx >>= f = f (ys ++ zs) (sx || sy || sz)              f ys sy = f x       f zs sz = if sy f [] false else f xs sx >>= f 

the last if discard xs part when f x signals stop.

nonstopguard :: bool -> f () nonstopguard true  = f [()] false nonstopguard false = f []   false 

a regular guard never signals stop. provides 1 or 0 choices.

stopguard :: bool -> f () stopguard true  = f [()] false stopguard false = f [] true 

a stopping guard instead signals stop becomes false.

fromlist :: [a] -> f fromlist xs = f xs false  tolist :: f -> [a] tolist (f xs _) = xs 

last caveat: i'm not sure monad instance defines actual monad, i.e. whether satisfies monad laws.


following suggestion of @icktoofay, wrote few quickcheck tests:

instance arbitrary => arbitrary (f a)    arbitrary = f <$> arbitrary <*> arbitrary  instance show (a -> b)    show _ = "function"  prop_monadright :: f int -> bool prop_monadright m =    (m >>= return) == m  prop_monadleft :: int -> (int -> f int) -> bool prop_monadleft x f =    (return x >>= f) == f x  prop_monadassoc :: f int -> (int -> f int) -> (int -> f int) -> bool prop_monadassoc m f g =    ((m >>= f) >>= g)    ==    (m >>= (\x -> f x >>= g)) 

running 100000 tests found no counterexamples. so, it's above f actual monad.


Comments

Popular posts from this blog

google chrome - Developer tools - How to inspect the elements which are added momentarily (by JQuery)? -

angularjs - Showing an empty as first option in select tag -

php - Cloud9 cloud IDE and CakePHP -