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
Post a Comment