wcのArrow版 via 趣味的にっき
趣味的にっき - Arrowを使ってwcコマンドを実装してみましたより
演算子じゃなくてパターンマッチっていうのが、いまひとつかっこ悪いのですが、何かいい方法ありませんかね?
趣味的にっき - Arrowを使ってwcコマンドを実装してみました
ということだったので、パターンマッチを使わずにやってみたんだけど、結局、(&&&)をたくさん使ってるので、タプルのネスト(?)の数を意識しなきゃいけなくなってしまいました。(&&&)は用法用量おまもりくださいだね。あと、個人的に関数は細かくしちゃいたい派なので、意味があるかわからないけど、関数をたくさん作りました。
$ cat wc_a.hs module Main (main) where import Control.Arrow add_t = (++) "\t" length_s = length >>> show >>> add_t line_w = lines >>> length_s word_w = words >>> length_s concat_a = uncurry (++) wc :: String -> String wc = line_w &&& word_w &&& length_s >>> (id *** concat_a) >>> concat_a main = getContents >>= putStrLn . wc
ホントは、とことんArrow使おうと、mainのモナドの部分もKleisli(未だにそらでスペルが書けない)を使おうと思ったんだけど、getContentsがIO Stringだから使えなくてやめました。
で、結果
$ ghc -o wc_a wc_a.hs $ wc wc_a.hs 12 61 342 wc_a.hs $ ./wc_a < wc_a.hs 12 61 342
追記:(add_t *** ( add_t *** add_t))の部分が気に入らなかったので修正
さらに追記:MaDさんより、const使えば、getContentsもKleisli(最近はKleisleとスペルミスを犯すようになってきました)が使えるとのこと。やってみました。
module Main (main) where import Control.Arrow add_t = (++) "\t" length_s = length >>> show >>> add_t line_w = lines >>> length_s word_w = words >>> length_s concat_a = uncurry (++) wc :: String -> String wc = line_w &&& word_w &&& length_s >>> (id *** concat_a) >>> concat_a wc_p = Kleisli ( const getContents) >>> arr wc >>> Kleisli putStrLn main = runKleisli wc_p ""
runKleisliがm a b -> a -> m bだから、かなりmainがキモイことに。使い方は、ホント考えないとな