To try out Pipes, I decided to write an over-engineered solution to the FizzBuzz "problem"<http://imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/> .
For the way I solved it, I needed a way to check if a 'Producer' is empty and conditionally pass on it's output or else run another 'Producer'. This is very similar to 'ifte'<http://hackage.haskell.org/package/logict-0.6.0.1/docs/src/Control-Monad-Logic-Class.html#ifte> from the logict package. So I wrote 'ifte' for pipes: module PipesBuzz where import Control.Monad import Pipes import Pipes.Internal -- |Logical condictional, \"if-then-else\". If the first argument sends any -- values downstream, these values will be fed into the success branch. -- Otherwise the failure branch is taken. -- -- @ -- 'ifte' :: 'Monad' m => 'Producer' a m r -> (a -> 'Effect' m ()) -> 'Effect' m r -> 'Effect' m r -- 'ifte' :: 'Monad' m => 'Producer' a m r -> (a -> 'Producer' b m ()) -> 'Producer' b m r -> 'Producer' b m r -- 'ifte' :: 'Monad' m => 'Pipe' a b m r -> (b -> 'Consumer' a m ()) -> 'Consumer' a m r -> 'Consumer' a m r -- 'ifte' :: 'Monad' m => 'Pipe' a b m r -> (b -> 'Pipe' a c m ()) -> 'Pipe' a c m r -> 'Pipe' a c m r -- @ -- ifte :: (Monad m) => Proxy a' a b' b m r -- ^ condition -> (b -> Proxy a' a c' c m b') -- ^ \"then\"-branch -> Proxy a' a c' c m r -- ^ \"else\"-branch -> Proxy a' a c' c m r ifte p0 th el = go p0 where go p = case p of Request x' fx -> Request x' (\x -> go (fx x)) -- at least one value sent upstream: run THEN branch Respond b fb' -> for (Respond b fb') th M m -> M (m >>= \p' -> return (go p')) -- no value sent upstream: run ELSE branch Pure _a -> el And here is my FizzBuzz solution using 'ifte'. The interesting part is the 'fizzify' function: fizzTest :: (Monad m) => Integer -> String -> Integer -> Producer String m () fizzTest d s n = when (n `mod` d == 0) (yield s) fizz, buzz :: (Monad m) => Integer -> Producer String m () fizz = fizzTest 3 "Fizz" buzz = fizzTest 5 "Buzz" fizzify :: (Monad m) => Integer -> Producer String m () fizzify n = do ifte (mapM_ ($n) [fizz, buzz]) yield (yield (show n)) yield "\n" fizzBuzz :: (Monad m) => Producer String m () fizzBuzz = for (each [1..100]) fizzify main :: IO () main = runEffect $ for fizzBuzz (lift . putStr) I would be interested in your thoughts regarding my use of pipes. Especially whether you think 'ifte' is a reasonable addition to pipes or that some other construct should be used instead. Cheers, Falko -- You received this message because you are subscribed to the Google Groups "Haskell Pipes" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected].
