最近、すこしずつ圏論の勉強と、Haskellの圏論関係のモジュールの勉強をしています (*´σー`)エヘヘ
練習問題として、 Control.Arrow を使って fizzbuzz を書いてみました
FizzBuzz
FizzBuzz.hs
import Control.Arrow
fizz :: Int -> Either Int String
fizz n = if n `mod` 3 == 0
then Right "Fizz"
else Left n
buzz :: Int -> Either Int String
buzz n = if n `mod` 5 == 0
then Right "Buzz"
else Left n
fizzbuzz :: Int -> Either Int String
fizzbuzz n = if n `mod` 15 == 0
then Right "FizzBuzz"
else Left n
fizzbuzzA :: Int -> String
fizzbuzzA = fizzbuzz >>> (buzz ||| Right) >>> (fizz ||| Right) >>> (show ||| id)
main :: IO ()
main = mapM_ (putStrLn . fizzbuzzA) [1..100]
あとがき
関係ないけど、 Arrow の do構文の展開、めちゃクソ面倒くさくないですか
追記
こっちのほうがカッコ良いですね
FizzBuzz.hs
whenMultipleOf :: String -> Int -> Int -> Either Int String
whenMultipleOf str m n = if n `mod` m == 0
then Right str
else Left n
fizzbuzzA_ :: Int -> String
fizzbuzzA_ = "FizzBuzz" `whenMultipleOf` 15
>>> "Buzz" `whenMultipleOf` 5 ||| Right
>>> "Fizz" `whenMultipleOf` 3 ||| Right
>>> show ||| id
Kleisli圏のArrowでもやってみた
FizzBuzz.hs
import Control.Arrow
fizz :: Kleisli (Either String) Int Int
fizz = Kleisli $ \n -> if n `mod` 3 == 0
then Left "Fizz"
else Right n
buzz :: Kleisli (Either String) Int Int
buzz = Kleisli $ \n -> if n `mod` 5 == 0
then Left "Buzz"
else Right n
fizzbuzz :: Kleisli (Either String) Int Int
fizzbuzz = Kleisli $ \n -> if n `mod` 15 == 0
then Left "FizzBuzz"
else Right n
fizzbuzzA :: Int -> String
fizzbuzzA = either id show . runKleisli (fizzbuzz >>> buzz >>> fizz)
main :: IO ()
main = mapM_ (putStrLn . fizzbuzzA) [1..100]