Hatena::ブログ(Diary)

あどけない話

2009-01-10

Haskell でグローバル変数が欲しい理由

nobsun さんよりグローバル変数というトラックバックを頂いたので、お答えします。

直前にあるコード例では、「処理結果(cflag など)を下位の関数にずっと渡していかないといけない」部分が省略されているようでよくわからない。

たとえば、UNIXod コマンドでは、-c オプションASCII 表記になります。それをunsafePerformIO なしで実装すると、僕だと以下のように書いてしまいます。

main = do argv <- getArgs
          let cflag = "-c" `elem` argv
          putStr $ func1 cflag

func1 cflag = func2 cflag

func2 cflag = func3 cflag

func3 cflag = func4 cflag

func4 cflag = if cflag
              then "ASCII string"
              else "HEX string"

別の方法としては、func4 内で getArgs を使い、func4 の型を IO String にすることですが、すると func1 〜 func3 までが全部 IO に侵されてしまいます。

僕の頭が C に毒されているだけで、もっとちゃんとした方法があるのかもしれませんね。

nobsunnobsun 2009/01/10 13:37 同僚と話しをしてみました。同僚の意見は、
「関数を定義するときに、その関数を引数に適用した結果を考えるのが普通だから、
引数を引き回している感覚になるのでは」でした。

私ならこんな感じの定義にするかな。

main = putStr . func1 . elem "-c" =<< getArgs
func1 = func2
func2 = func3
func3 = func4
func4 cflag = if cflag then "ASCII string"
else "HEX string"

これならそれほど、cflag の引き回し感がないのではと思います。

Otter_OOtter_O 2009/01/10 21:18 こんにちは。

それぞれのオプションに対応する機能を別々の関数にして、その関数をパラメタにしてやるとかっこいいかなと思ったので、やってみました。

module Main where

import System.Environment
import Text.Printf

main = putStr . func1 . getProc. elem "-c" =<< getArgs

getProc True = id
getProc False = concatMap toHex

toHex :: Char -> String
toHex = printf "%x,".fromEnum

func1 = func2

func2 = func3

func3 = func4

func4 :: (String -> String) -> String
func4 f = f "ASCII string"


あと、Global Variables in Haskell というFunctional Pearlsもあります。これでは、IORefをつかった、グローバルをunsafePerformIOで参照する方法と、implicit parameters(暗黙パラメタ)という方法がとりあげられています。暗黙パラメタは結果としてはnobsunさんのサンプルにとてもよく似た動きをします。

kazu-yamamotokazu-yamamoto 2009/01/11 21:47 nobsun さん、
コメントありがとうございます。
僕の知らない方法がある訳ではないと理解しました。
これから書くコマンドには引き回す方法も使ってみようとは思いますが、直観的に言えば、煩雑で面倒だろうなと思います。
逆にグローバル変数にするのが悪いという理由があれば教えて下さい。
僕の周りで議論したところでは、コマンドラインオプションは*不変*の環境であり、どの関数からも直接アクセスできてしかるべきだ、となっています。
値が変わりうるグローバル変数は忌み嫌われますが、グローバル定数を嫌う理由はないと思っています。

kazu-yamamotokazu-yamamoto 2009/01/11 21:48 Otter_O さん、こんにちは。

論文を教えて頂き、ありがとうございます。その内読みますね。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証