1 名前:デフォルトの名無しさん mailto:sage [2008/05/17(土) 16:41:29 ] haskell.org www.haskell.org/ 日本語サイト www.sampou.org/cgi-bin/haskell.cgi www.shido.info/hs/ 過去ログ 関数型プログラミング言語Haskell Part1 pc.2ch.net/tech/kako/996/996131288.html Part2 pc2.2ch.net/test/read.cgi/tech/1013846140/ Part3 pc8.2ch.net/test/read.cgi/tech/1076418993/ Part4 pc8.2ch.net/test/read.cgi/tech/1140717775/ Part5 pc8.2ch.net/test/read.cgi/tech/1149263630/ Part6 pc11.2ch.net/test/read.cgi/tech/1162902266/ Part7 pc11.2ch.net/test/read.cgi/tech/1174211797/ Part8 pc11.2ch.net/test/read.cgi/tech/1193743693/ ・2chの仕様により、行頭の半角スペースは表示されません。 コードをインデントしたいときは、代わりに または全角スペースを使うことができます。
175 名前:デフォルトの名無しさん mailto:sage [2008/06/04(水) 03:18:52 ] Haskell実用経験皆無の俺が来ましたよ >>168 4.1 Overview of Types and Classes > but the type system has been extended with type classes (or just classes) > that provide a structured way to introduce overloaded functions. 型クラスの存在意義がわかるかどうかだと思う。 整数の足し算と有理数の足し算って、ふつう同じ記号を使うけど、 計算の内容は違う(多重定義、オーバーロードされている)でしょ。 でも、共通の性質を考えたいときもある。 そのとき、ただ「共通の演算記号+を使っているから同類とみなす」では話にならないから、 twice :: a -> a twice x = x + x -- 2倍したいけど、+の型などがコンパイル時に不明 +を「Numという型クラスの特徴」として整理して、整数や有理数はその特徴を共有している、とみなすと。 twice :: Num a => a -> a -- 「型aはクラスNumに属する(Numのインスタンスである)」という前提をする twice x = x + x -- と、演算子+の存在と型が保証される そんな感じ?(ごめん、確認してない)
176 名前:デフォルトの名無しさん mailto:sage [2008/06/04(水) 07:01:52 ] 改めて見るとオーバーロードの解釈が破綻してるなw すまぬ
177 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 00:09:02 ] => C++のテンプレートの特殊化みたいなものか 演算子は定義されているけど特定の型じゃないと 処理できない場合、特定のの変数を特殊化すること あるけど
178 名前:初心者修業中 mailto:sage [2008/06/05(木) 00:54:30 ] >>177 日本語でお願いしますm(_ _)m
179 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 08:24:10 ] Haskellian ももうブランドではなくなりましたね… メジャーになった証か
180 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 08:41:12 ] => の意味は総称型に制限を与える、じゃだめなのかなぁ。 質問、というより興味本位のアンケート。 あなたが思うhaskellの面白いところってどこですか?
181 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 09:05:56 ] アホな質問するスレがあるところ
182 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 16:59:32 ] 堅い言語なのに簡潔に書けるようになってるところが面白いと思うし、すごく好きだ 記号を多用してたり、インデントを使ってたり
183 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 18:54:01 ] 「haskell使ってる」と言うと、みんなに尊敬して貰えること
184 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 19:19:05 ] >>180 高速化を考え出すと、すごくたいへんなところ。
185 名前:デフォルトの名無しさん [2008/06/05(木) 21:02:04 ] [(x,y) | x + y = 10]
186 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 21:59:49 ] >>183 このスレ見てたらそう思えんわな、、、
187 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 22:55:55 ] 知らない人は知らないし、知ってる人はわかるもんな しかしいい言語だ
188 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 23:02:27 ] 汎関数系の言語はC++もそうだが、 かなり野心的な言語設計になるね。 クラス囲い込み度が低いからだろうか。
189 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 23:56:07 ] >>185 そんなのできたの!?と思って ghci で試したらできなかった。 ちょっと悲しくなった。
190 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 00:00:22 ] インデントがよくわからなくて エラーでていらつく なんとかならんのかね?この糞言語 インデント制約糞なら最初からなんか そういう機能入れろよなぁ あーあー世界で最悪の糞言語だね インデントのせいだけで
191 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 00:12:41 ] >>190 そういう説もあります。 そうでないという説もあります。
192 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 00:29:14 ] インデントがいやなら { } と ; で全部区切ればいいじゃん 一緒だよ
193 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 00:37:44 ] traceの使い方qsortのサンプル使って 教えてくれませんか? qsort _ [] = [] (1) qsort f (x:xs) = before ++ (x : after) (2) where before = qsort f (filter (not . (f x)) xs) (3) after = qsort f (filter (f x) xs) (4) どこにいれればいいのやらw
194 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 03:41:00 ] それを見つけるのにもtraceが役立つのではないか
195 名前:初心者修業中 mailto:sage [2008/06/06(金) 05:35:07 ] >>193 私はまだtraceに手を出すつもりはありませんが、 ググってみました。 参考になるでしょうか…? ↓ 第15回 Haskellでのデバッグのコツをつかむ ttp://itpro.nikkeibp.co.jp/article/COLUMN/20071204/288630/?P=2 import Debug.Trace quicksort[] = [] quicksort(x:xs) = trace ("x." ++ show x) $ trace ("x." ++ show x ++ " > y." ++ show losort) $ trace ("x." ++ show x ++ " <= y." ++ show hisort) $ losort ++ [x] ++ hisort where losort = quicksort [y|y <- xs, y < x] hisort = quicksort [y|y <- xs, y >= x] Main> quicksort [3,2..1] x.3 x.2 x.1 x.1 > y.[] x.1 <= y.[] x.2 > y.[1] x.2 <= y.[] x.3 > y.[1,2] x.3 <= y.[] [1,2,3]
196 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 07:41:25 ] [(x,y) | x <- [1..], y <- [1..], x+y = 10]
197 名前:初心者修業中 mailto:sage [2008/06/06(金) 08:06:28 ] >>196 これ、やってみたけど止まりませんね…。 *Main> take 10 [(x,y)|x<-[0..],y<-[0..],(x+y)==10] [(0,10) x=0 のままyの無限リストを検索してるから当たり前ですけど… *Main> take 10 [(x,y)|x<-[0..],y<-[0..]] [(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(0,9)] ↓みたいなリストを返す簡単な方法ありますかね…? [(0,0),(1,0),(0,1),(2,0),(1,1),(0,2).....]
198 名前:初心者修業中 mailto:sage [2008/06/06(金) 08:42:12 ] こんなもんかな… tlist::[(Int,Int)] tlist = concatMap (\n ->f n) [0..] where f = \n->take (n+1) $ iterate (\(x,y) ->(x-1,y+1)) (n,0) *Main> take 10 tlist [(0,0),(1,0),(0,1),(2,0),(1,1),(0,2),(3,0),(2,1),(1,2),(0,3)] *Main> take 10 [(x,y)| (x,y)<-tlist, (x+y)==10] [(10,0),(9,1),(8,2),(7,3),(6,4),(5,5),(4,6),(3,7),(2,8),(1,9)]
199 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 08:43:25 ] つまらない答えだが [(x,y) | k <- [0..], x <- [0..k], y <- [0..k], x + y == k]
200 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 08:52:37 ] つまらないのならこれが一番 [(x, 10-x) | x <- [0..10]]
201 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 08:54:12 ] >>199 間違ってるやん!
202 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 09:51:55 ] [(a,b) | x <- [0..], y <- [0..x], x + y == 10, (a,b) <- [(x,y), (y,x)]] こんなんできたっけ
203 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 09:52:48 ] なんだ(a,b)って t <- [(x,y), (y,x)]
204 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 10:16:24 ] >>190 Pythonに見られるインデントによる制御構造の是非 pc11.2ch.net/test/read.cgi/tech/1169473442/l50
205 名前:初心者修業中 mailto:sage [2008/06/06(金) 14:27:09 ] >>202-203 なるほど、そういう事もできるのですね。 *Main> take 12 [t | x <- [0..], y <- [0..x], (x+y)==10, t<-[(x,y),(y,x)]] [(5,5),(5,5),(6,4),(4,6),(7,3),(3,7),(8,2),(2,8),(9,1),(1,9),(10,0),(0,10)] リストモナドの>>=はconcatMapでしたもんね。 勉強になります。 (5,5),(5,5)がだぶってるのが、おしいですね。
206 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 15:16:52 ] GHC 6.8.3 まだー?
207 名前:デフォルトの名無しさん mailto:sage [2008/06/06(金) 18:05:51 ] >>206 作って公開してくれ。
208 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 00:31:44 ] 無明関数って何がうれしいの?
209 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 00:52:24 ] いちいち関数の名前考えなくても良い 名前をつけるまでもない単純な関数を作る時に便利
210 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 01:08:37 ] 名前を付けることは名前空間を汚染すると言うこと 名前よりも式そのもののほうが理解しやすい場合もある
211 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 01:24:35 ] getChar >>= \a -> getChar >>= \b -> putChar b >> putChar a こういうのに名前つけるのはいやだな
212 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 02:04:23 ] >>208 そういう話題は関数型言語スレのほうが向いている。 関数型言語一般について語れるよ。
213 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 02:12:55 ] >>208 どんなバックグラウンドをもってる?関数型言語についての経験は? 手続き型の国の人ならば、わかりにくいところやね。 関数を変数でもたすってのは関数型では日常茶飯事なんですわ。 そこに便利さのヒントがアルよ。
214 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 07:57:49 ] map (\(a, b) -> a+b) [(1,1), (2, 3) ..]
215 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 10:56:31 ] >>213 手続きの国からワープしてきたのですが 関数を変数にするならポインタ渡せばよくないですか? そうすれば、定義しても渡せますよね?
216 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 11:20:46 ] 名前があってもなくてもポインタ渡すのです 関数オブジェクトは、メソッドがひとつしかないクラスのインスタンス、に似ています インスタンスに名前がついているとは限らないのです
217 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 11:33:06 ] >>216 よくわからないぉ もう少し詳しく説明してぉ?
218 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 11:43:32 ] 無明関数…悟りでも得たいのか?
219 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 11:46:43 ] >>218 間違えただけだぉ気にしないで
220 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 11:47:44 ] >>218 悟りは得るものではなく開くものです。
221 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:06:14 ] 名前を考えるのが面倒くさい 再利用しない 定義している箇所を探すのが面倒くさい 関数内部の処理が簡潔 のときは無名関数使いたくならないか?
222 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:14:34 ] つーか、関数本体そのものずばりを一覧できる状態で渡しているのにわざわざ名前をつける必要があるのだろうか
223 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:28:02 ] カリー化 (new Satori(x)).open(y)
224 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:43:21 ] 無名関数で再帰するにはどうすればいいですか たとえば、 f n = if n == 1 then 1 else n * f (n-1) はどのように書けばいいですか?
225 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:46:45 ] fix (\f n -> if n == 1 then 1 else n * f (n-1)) むみょーん。Haskellian じゃないから fix があるかどうかシラネ
226 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:49:20 ] 型無し言語なら (\f -> f f) (\f n -> if n == 1 then 1 else n * f f (n-1))
227 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:54:26 ] あー、でも f って名前つけちゃったな
228 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 13:11:01 ] >>225-226 ここはHaskellのスレですよ
229 名前:初心者修業中 mailto:sage [2008/06/07(土) 13:17:55 ] >>225 Control.Monad.Fix にありますね。 fix :: (a -> a) -> a fix f = let x = f x in x
230 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 13:22:40 ] >>224 不動点演算のfixを使うようです。 Prelude> Control.Monad.Fix.fix(\f n -> if n == 1 then 1 else n * f (n-1)) 5 120
231 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 14:00:44 ] (\y f -> f (y f)) (\y f -> f (y f)) (\y f -> f (y f)) (\y f -> f (y f)) ...
232 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 14:16:56 ] >>224 ... f ... where f n = if n == 1 then 1 else n * f (n-1) 局所的な関数定義で代わりになるんじゃないの、というのはダメかな
233 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 16:01:17 ] >>232 に同意
234 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 16:19:36 ] 名前が付いてるからダメ
235 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 16:37:58 ] ... (f where f n = if n == 1 then 1 else n * f (n-1)) ... こうかー
236 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 17:21:15 ] >>235 whereが作るのは式じゃなくて節だから使える場所が決まってる(定義の後とかcase選択肢の後とか) ... (let f n = if n == 1 then 1 else n * f (n-1)) in f) ... ならおk
237 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 17:22:54 ] 閉括弧が一個多かった ... (let f n = if n == 1 then 1 else n * f (n-1) in f) ...
238 名前:デフォルトの名無しさん mailto:sage [2008/06/09(月) 21:46:25 ] The Haskell School of Expressionで勉強してます。 この本の解答集のようなもの、ネットには無いでしょうか。 www.elbeno.com/haskell_soe_blog/ ↑このページは参照してますけど、11章までなので、全部が まとまったのがあると嬉しいです。
239 名前:デフォルトの名無しさん [2008/06/16(月) 14:44:56 ] ポイントフリースタイルについて質問なんですが、 Haskellでは原理的にどんな関数でもポイントフリースタイルに 変形可能なのでしょうか。
240 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 15:00:34 ] うん
241 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 18:48:23 ] >>239 Sコンビネータとかもポイントフリーに出来るんだっけか?
242 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 18:52:01 ] どの範囲の関数まで使用を認めるかによるな >>241 Control.Monad.ap :: (Monad m) => m (a -> b) -> m a -> m b を(->) rモナドについて使えば、Sコンビネータそのもの
243 名前:デフォルトの名無しさん [2008/06/17(火) 22:58:00 ] ポイントフリーのポイントって何? 何が自由なの?
244 名前:デフォルトの名無しさん mailto:sage [2008/06/17(火) 23:28:00 ] ポイント = initial objectからのarrow ポイントフリースタイル = ポイントを使わない関数定義
245 名前:デフォルトの名無しさん mailto:sage [2008/06/18(水) 00:11:23 ] (Monad m) => m (a -> b) -> m a -> m b これって未だによくわからないけど 手計算できそうな実例ないですか?
246 名前:デフォルトの名無しさん mailto:sage [2008/06/18(水) 00:28:46 ] あんまり意味ないけど↓こんなのとか? f :: Monad m => m (a -> b) -> m a -> m b f mg mx = do { g <- mg; x <- mx; return $ g x } test1 = f Nothing (Just 1) test2 = f (Just succ) (Just 2) test3 = f (Just id) Nothing test4 = f [] [] test5 = f [id] [5] test6 = f [id, succ, (* 2)] [6, 9]
247 名前:デフォルトの名無しさん mailto:sage [2008/06/18(水) 09:12:38 ] GHC 6.8.3リリース
248 名前:デフォルトの名無しさん mailto:sage [2008/06/18(水) 11:53:17 ] ナイス
249 名前:デフォルトの名無しさん mailto:sage [2008/06/18(水) 14:40:13 ] >>244 initial object(始対象)じゃなくて terminal object(始対象)だお。 集合の圏で terminal object からの arrow というと一点集合に相当する。 集合の圏では任意の一点集合 x に対して f x = g x ならば f = g 「point(一点集合)を使わずに関数が等しいことを表現できる」=>「ポイントフリー」ということだと思う。
250 名前:デフォルトの名無しさん mailto:sage [2008/06/18(水) 18:25:28 ] >>249 失礼、書き間違えた。 terminal object(終対象)だな。
251 名前:249 mailto:sage [2008/06/18(水) 18:26:24 ] × terminal object(始対象) ○ terminal object(終対象) だった。
252 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 11:33:25 ] 俺やべぇ 気がついたらポイントフリースタイルで5行も書いてたぜ これはもはや関数型スパゲッティだな
253 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 12:48:07 ] 任意のλ式はSKコンビネータで書き換えられるとか言うのを見て 実際に適当なλ式で変換してみたら出てきた式はとても読める 代物ではなかったのを思い出した
254 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 15:00:42 ] ありゃ一種の難読化だよな
255 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 18:06:18 ] >>253 SKコンビネータも、名前付きにできると若干読みやすそうだけど。 っていうか、それが出来たら、どんな高級言語とも変らんという話になって、逆に面白さがないか。
256 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 19:22:12 ] >>255 そこでunlambdaですよ!
257 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 00:27:42 ] >>255 つ super combinator
258 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 17:45:00 ] 以下の関数fをもっと簡単にする方法ありませんか? f [] = [] f (_:[]) = [] f (x:xs) = (x, head xs) : f xs
259 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 17:52:53 ] 簡単に、というより再帰を使わずにできませんか?
260 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 18:05:14 ] f xs = zip xs (tail xs)
261 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 18:15:27 ] f xs = zip xs (drop 1l xs)
262 名前:261 mailto:sage [2008/06/23(月) 19:03:55 ] すまん。tail の l を残してしまった。 f xs = zip xs (drop 1 xs)
263 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 19:21:38 ] zip [] ⊥ = [] らしいから>>260 と>>261 は等価かな こういうのを意識しないといけない場面だと非正格性が気持ち悪い
264 名前:デフォルトの名無しさん mailto:sage [2008/06/24(火) 00:09:28 ] >>263 ⊥って勃起してるのw?
265 名前:デフォルトの名無しさん mailto:sage [2008/06/24(火) 01:03:13 ] いやむしろ tail で書けて気持ちいいだろ。
266 名前:デフォルトの名無しさん mailto:sage [2008/06/24(火) 06:18:25 ] >>265 でも zip (tail xs) xs と zip (drop 1 xs) xs は等価じゃない つまり、zipでは第一引数が先に評価されるということを覚えていないといけない分、ややこしい (厳密には評価順の問題じゃなくて「zipは第一引数について正格で第二引数について非正格」ということだけど)
267 名前:デフォルトの名無しさん [2008/06/24(火) 07:48:57 ] >>266 どういうこと? 例えば f (x1 : x2 : x3 : xs) -> x1 + x3 だったら、引数のリストの最初の要素と3番目の要素について正格ってこと?
268 名前:デフォルトの名無しさん mailto:sage [2008/06/24(火) 08:32:09 ] >>267 そういうつもりで「正格」という言葉を使った
269 名前:初心者修業中 mailto:sage [2008/06/24(火) 09:53:02 ] 関数結合の(.)って優先順位が高いので、 どうしても括弧が増えて見ぐさい気が…。 こんなのがあったら便利だと思うんですけど、 ↓ infixr 1 $. ($.)=(.) こんな感じ ↓ sigma = tail $. scanl (+) 0 標準ではなさそうなんですが、 やっぱ、問題ありですかね?
270 名前:デフォルトの名無しさん mailto:sage [2008/06/24(火) 09:55:22 ] 慣れの問題
271 名前:初心者修業中 mailto:sage [2008/06/24(火) 10:13:14 ] ああ、勘違いしてました。 関数の優先順位はどの演算子よりも上ですね。 これで問題ないのか ↓ sigma = tail . scanl (+) 0 >>270 レスありがとうございます。 早く慣れたいです。 まだ、頭で考えないとよくわからない。 (考えてもわからない時ありw)
272 名前:デフォルトの名無しさん mailto:sage [2008/06/24(火) 11:35:10 ] >>266 「厳密には」も何も最初っからそう
273 名前:デフォルトの名無しさん mailto:sage [2008/06/24(火) 12:56:24 ] >>266 > 覚えていないといけない 覚えてなくてもプログラム書くのにはなにも困らない。 等価性とか考えだすと全部正格のほうが楽かもしれんけど。
274 名前:デフォルトの名無しさん mailto:sage [2008/06/24(火) 18:49:23 ] >>273 書くときは良くても読むとき困る 例えば>>260 のコードが空リストに対しても正しく動作するかどうか確かめるのに、 いちいちPreludeの仕様を読まないといけない zipみたいに明確な定義のある関数ならまだいいけど、 例えばhPutStrLn undefined ""の値が 1. ⊥ 2. 実行時にエラーになるアクション 3. ()を返すアクション のどれになるかは仕様では決まっていないはずで、ちょっと厄介
275 名前:デフォルトの名無しさん mailto:sage [2008/06/25(水) 15:42:16 ] >>274 その辺は想像で読めば十分じゃない? zip xs (tail xs) とあって、 コードを書いたのが信頼できる人なら、 zip は第二引数について非正格なのだろうな、とか。 hPutStr undefined "" も、 hPutStr _ "" = return () と定義されては無いだろうし、 undefined が正しいハンドルじゃないからと hPutStr が独自にエラーを出すというのも、 先に undefined が評価されるから有り得ないだろう、とか。 hPutStr (error "1") (error "2") にしても error "1" だろう、とか。