shelarcyです。

On Sun, 13 Apr 2003 19:54:27 +0900, Shinya Hayakawa 
<tetryl / tokyoprogrammer.com> wrote:
>> Haskell では関数を引数にとることができるし、「.」(関数合成)が関数の
>> 定義に使えるので、いわゆる Design Pattern の Template Method は不
>> 要です。
>
> 上記の Haskell のメリットから、なぜ Template Method が不要
> となるのかが分かりません..
> 何か具体的な例などは、ありませんでしょうか。
> ...
> Haskell の記述力には、感激してばかりですが
> 実務で使おうとすると泥臭いコードだらけになってしまいそうで..
> 理解できていない&使いこなせていないのだと思いますが。

もしかしたら、オブジェクト指向の考え方に囚われていのではないでしょうか?

言ってみれば関数型で構築されるオブジェクトはCLOSや存在論などの何らかのクラス
機構をもたない限り強制的にVisitorなオブジェクトのようなものです。(OHaskellに
ついてはよく知りませんが)
よってオブジェクト指向的なやり方はうまくいきません。

genericsを使わないオブジェクト指向(詳しくは説明しませんがtemplateなどの
genericsを含めてオブジェクト指向なんだという考え方もあります)では
オブジェクトを中心に組み立てていくのに対し、関数型では関数を中心にデータ型
に対し特殊化した関数を与える形になります。

ええと、つまり、オブジェクト指向のやり方では役割ごとに次々と違うオブジェクトを
作っていくのに対し、関数型言語では次々と特殊化・カリー化した関数を定義していく
ことになります。


> モジュール利用者は、新しい型、必要なメソッドを定義して
> run を呼び出します。
> -- 話を簡単にするため CustomerDataObject は無引数になってます
>
> これを元のコードを無視して、Haskell のメリットを最大限に
> 生かすよう書き換えるには、どういうアプローチがありますでしょうか。
>
> 自分なりに考えたものは以下の通りです。
>
> $ cat DataObject.hs
> module DataObject where
>
> run :: a -> (a -> IO ()) -> (a -> IO ()) -> (a -> IO ())
> -> (a -> IO ()) -> IO ()
> run o c s p d = do {c o; s o; p o; d o}
>
> $ cat try.hs
> module Main where
>
> import DataObject
>
> connect    obj = print "connect"
> select     obj = print "select"
> process    obj = print "process"
> disconnect obj = print "disconnect"
>
> main = run "foo" connect select process disconnect

この場合、connect に対応する disconnect が必要になるのは
分かりきっているので、

myrun foo hoge huga = run foo connect hoge huga disconnect

ということをやるのが常套手段になります。


基本は自分のやりたい操作を直接的にできる関数をたくさん定義して、
同じ操作が多くなってきたら中間の関数にリファクタリングしていく
という感じでよいかと思います。



-- 
shelarcy <shelarcy / capella.freemail.ne.jp>
http://page.freett.com/shelarcy/ 

--
ML: haskell-jp / quickml.com
使い方: http://QuickML.com/