https://qiita.com/tezca686/items/78d099987894ac7bec48#comment-1d42663d1411baab921e
対象が1つ(ここでは a )だけの圏は、合成演算によってモノイドとなることが知られてますので、 {f :: a -> m a} は >=> によってモノイドとなります。
実際にそのようなモノイドインスタンスが用意されているので、コードでの実例。ここでは <=<
でモノイドになっている( Control.Category.Dual
使えば >=>
にもできる)。
#!/usr/bin/env stack
-- stack --install-ghc runghc --package monoid-extras
import Control.Arrow (Kleisli(..))
import Data.Monoid ((<>))
import Data.Monoid.Endomorphism (Endomorphism(..))
import System.Environment (getEnv)
main :: IO ()
main = do
-- String -> IO String 型の関数を wrap するとモノイドになる
unwrap (wrap return <> wrap readFile <> wrap getEnv) "SOME_FILE_PATH"
>>= putStrLn
-- putStrLn :: String -> IO () はモノイドにできない
-- unwrap (wrap putStrLn <> wrap return <> wrap readFile <> wrap getEnv) "SOME_FILE_PATH"
where
wrap = Endomorphism . Kleisli
unwrap = runKleisli . getEndomorphism
なんかもっと直接的なインスタンスもあったような気もするけど、気のせいかもしれない。