c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

Haskellでmain = (〃|_|) .。oO("さっちゃん☆")

[.。oO(さっちゃん Advent Calendar) http://atnd.org/events/22829 ]10日目
今日はHaskell初心者以前のさっちゃんが、しぇらーしいさまの手になる以下のコードがなぜ動くのか読んでみたいとおもいます。あ、Opera忘年会で会ったら呼んでください。詠んでくださってもいいです>ω<

-- http://favstar.fm/users/shelarcy/status/130666089607725056
-- http://favstar.fm/users/shelarcy/status/142682424680259584
import System.IO
(〃|_|) = \str -> hSetEncoding stdout utf8 >> hPutStrLn stdout str

(.。) = ($)
(oO) = id

main = (〃|_|) .。oO("さっちゃん☆")
$ runghc momonga.hs
さっちゃん☆

1行目

import System.IO

System.IOモジュールをimportしていますね。

2行目

(〃|_|) = \str -> hSetEncoding stdout utf8 >> hPutStrLn stdout str

関数定義ですね。左右に分けましょう。

(〃|_|) =

これは〃|_|と云う名の関数を定義しています。()で囲ってあるのは、英数文字じゃないからですね。そのまま書いてはparse errorに成ってしまいます。(+)などと同じですね。
_も全角ですが、特に全角である必要性は無い様です。ただ、途中に空白を空けてはなりません。parse errorが吐かれます。

\str -> hSetEncoding stdout utf8 >> hPutStrLn stdout str

\は無名関数lambdaですね。strと云う引数をとる関数です。
関数本体は何でしょう? これはstrをコンソールに出力する処理です。コンソールに出力する処理ならば、putStrLnがあるのではないでしょうか? ghciで見てみましょう。

Prelude> :type putStrLn
putStrLn :: String -> IO ()
Prelude> "さっちゃん☆"
"\12373\12387\12385\12419\12435\9734"
Prelude> putStrLn "さっちゃん☆"
Uca▒▒

うわあああああああヾ(〃l _ l)ノ゙ Uca▒▒ってなんだぁ。どうやらputStrLnUnicode文字の出力はできないようです。ではhSetEncodinghPutStrLnは何でしょう?

Prelude> :type (>>)
(>>) :: Monad m => m a -> m b -> m b
Prelude> import System.IO
Prelude System.IO>  :type hSetEncoding
hSetEncoding :: Handle -> TextEncoding -> IO ()
Prelude System.IO> :type  hPutStrLn
hPutStrLn :: Handle -> String -> IO ()
Prelude System.IO> :type \str -> hSetEncoding stdout utf8 >> hPutStrLn stdout str
\str -> hSetEncoding stdout utf8 >> hPutStrLn stdout str
  :: String -> IO ()

Handleにstdoutを指定して、TextEncodingのutf8を設定していますね。
>>というのは、アクションを順次実行するよう繋ぐものです。アクションとは、たとえばIOの様な、副作用をともなう故に「関数」ではない奴等だそうです。
因みに瑣末ですがこれは、\str -> hSetEncoding stdout utf8 >> putStrLn strでも同様に動作します。

3, 4行目

(.。) = ($)
(oO) = id

$idに別名を定義していますね。idは恒等関数です。ではなぜ(.。oO) = ($)ではダメなのでしょう? 実際これはparse errorになります。わからないのでパス。きっとUnicode文字関連です。

Prelude> :type id
id :: a -> a
Prelude> :type ($)
($) :: (a -> b) -> a -> b

$は、関数の連鎖に近い見た目を作れる演算子(=関数)ですね。f $ aで、fにaを部分適用します。Haskellでは全ての関数がカリー化(壱引数関数化)されていることの、威力ですね!

5行目

main = (〃|_|) .。oO("さっちゃん☆")

いよいよ文字列を出力するmain関数ですね。(〃|_|)String -> IO ()でいいとして、別名は書き換えてみましょう。

main = (〃|_|) $ id "さっちゃん☆"
Prelude> :type ($)id
($)id :: b -> b

$ ididと同じ型ですね。因みにこのコードは、main = (〃|_|) id "さっちゃん☆"でも、main = (〃|_|) $ "さっちゃん☆"でも、main = (〃|_|) "さっちゃん☆"でも、同様に動作します。恒等関数ですからね!

こっちのコードも

もう読めますね! 型宣言がついているのみです。

-- http://favstar.fm/users/shelarcy/status/130666089607725056
import System.IO

(〃|_|) :: String -> IO ()
(〃|_|) = \str -> hSetEncoding stdout utf8 >> hPutStrLn stdout str

main = (〃|_|) "ももんが"

参考

Real World Haskell―実戦で学ぶ関数型言語プログラミング

Real World Haskell―実戦で学ぶ関数型言語プログラミング