1 名前:デフォルトの名無しさん mailto:sage [2007/08/05(日) 14:49:54 ] 関数型言語MLについて語るスレッドです。 MLは、確固とした理論的背景を持つ言語でありながら、 現実的なソフトの開発にも使用できる実用性を備えた言語です。 また、プログラミングの初心者が最初に学習する言語としても優れています。 総本山 Standard ML www.smlnj.org/ Objective Caml caml.inria.fr/ocaml/ 前スレ 関数型言語ML(SML, OCaml, etc.), Part 4 pc11.2ch.net/test/read.cgi/tech/1133003340/
370 名前:デフォルトの名無しさん mailto:sage [2008/05/19(月) 08:58:50 ] > ライブラリの形で別言語を実装しておいて 言語内の機能で実装しているんだぜ?
371 名前:デフォルトの名無しさん mailto:sage [2008/05/19(月) 21:49:06 ] クロージャはファーストクラスじゃないとね
372 名前:デフォルトの名無しさん mailto:sage [2008/05/19(月) 22:47:50 ] >>370 それいうとあらゆる言語が関数型を名乗れるから。
373 名前:デフォルトの名無しさん mailto:sage [2008/05/19(月) 23:02:44 ] >>370 それいったらアセンブラだって関数型だろwww
374 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 06:52:47 ] つまらんんこと言っとらんでコード書け。
375 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 08:27:19 ] C++のboost:lambdaみたいなのを、 言語の本来の機能で実装できるのってないんじゃねえ?
376 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 10:04:38 ] >>375 boost.lambda 見てないんだけど Lisp のマクロ、R6RS のマクロでも無理?
377 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 11:19:19 ] 関数型は最初からラムダ式があるから必要ないのでは。 zip(list1, list2, _1 + _2) //←こんな感じ。
378 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 17:44:55 ] Boostはポリシーによるプログラミングができる (lambda (lambda (funcname)) (funcname ...)) ↑こんなイメージ。これはLISPだったらマクロなしだと実現不可能じゃない? 型システムが閉じてないことが前提だから OcamlやF#ではこれ、実現不可能だと思う //ちら裏:自分はBoostが関数型言語やろうと思ったきっかけ
379 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 17:52:12 ] >>378 マクロ書けばええやん? 言語本来の機能でっせ、Lisp のマクロは…
380 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 18:56:16 ] >>378 >LISPだったらマクロなしだと その前提が間違い。何の為の S 式だか。
381 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 22:14:56 ] すまん、今の流れでマクロなしってのは間違ってるなw しかし、マクロありでもポリシーによるプログラミングはLISPでは不可能なんじゃね? ここでS式が出てくるのはなぜ? 静的な型を持つ言語じゃないとコンパイル時型チェックの利点はなくなるし 単なるダックタイピングになってしまう 現時点では閉じていない多態かつ静的な言語って 俺が知る限りC++ぐらいしかないけど他にあるのかな Template Haskellとかどうなんだろ
382 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 22:19:20 ] >>381 >ここでS式が出てくるのはなぜ? 興味無いくせに聞くなよ
383 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 22:26:20 ] >>381 declare すりゃいい話だし、元気があればコンパイラ書き換えれば OK 型推論でも何でもできるんじゃないか?
384 名前:デフォルトの名無しさん mailto:sage [2008/05/20(火) 22:28:55 ] ああ、コンパイラ作るのか・・その発想はなかったわw
385 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 21:52:19 ] >>384 つか, 処理系自体にシンタックスパーサからコンパイラまで含んでて そいつらを自前の定義に書き換え可能な言語相手に何を戦ってるんだか
386 名前:デフォルトの名無しさん mailto:sage [2008/05/21(水) 23:06:06 ] >>378 すまんが、このコードで何をしてるのか参考までに教えてくれ・・・ >>385 C++に脳を冒されて、そんな言語が存在することを知るよしもないんだろう
387 名前:デフォルトの名無しさん mailto:sage [2008/05/22(木) 05:23:56 ] >>339 いや、セーフだろ
388 名前:デフォルトの名無しさん mailto:sage [2008/05/22(木) 07:28:36 ] 職場で出た話題。 O'Caml で、v == v は真なのに v = v は偽な値 v は存在するか。
389 名前:デフォルトの名無しさん mailto:sage [2008/05/22(木) 08:16:39 ] NaN
390 名前:デフォルトの名無しさん mailto:sage [2008/05/22(木) 21:55:52 ] >>375 >静的な型を持つ言語じゃないとコンパイル時型チェックの利点はなくなるし OCamlは型推論で静的な型が付くからC++並にコンパイル時型チェック働くよ 型変換がらみのバグ出づらい分むしろ安全だと思うけど。 (* てかboost:lambdaコンパイル遅すぎ *)
391 名前:デフォルトの名無しさん mailto:sage [2008/05/22(木) 23:38:28 ] >>390 OCAMLだとこれに相当することができない(STLC<U>が定義済みの場合だけOCamlでも可能) C++では定義済みかどうかは関係なく宣言できる STLライクなデータに対する探索コード template <template <typename T> class STLC,typename U,typename R> bool has_data(STLC<U>&data,const R&value){ typename STLC<U>::iterator it = std::find(data.begin(),data.end(),value); if(it!=data.end())return true; else return false; }
392 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 00:30:15 ] begin(data)がイテレータ関数を戻すなら find(b,v)はdataの型と関係なく定義出来る (イテレータ関数の型には影響をうける) クロージャ使えるって忘れてない?
393 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 01:10:33 ] >>391 > 宣言できる 「定義できる」かな? 宣言ももちろんできるけど。
394 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 01:17:03 ] 念のため言っておくけど、上はあくまでどうしてもイテレータ使いたいならの話 リストは、|でパターンマッチして再帰でグルグルが普通
395 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 01:22:07 ] 要は先に定義が必要だったりはしないので、391は間違ってると思われ
396 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 01:39:44 ] >>391 の例自体は不適切かもしれんが、C++のテンプレートにできて他の殆どの言語にできないことがあるのは事実だよ C++のテンプレートの顕著な特徴は ・型検査と名前解決の一部がインスタンス化まで遅延される ・特殊化(テンプレート引数に対するパターンマッチ)ができる で、メジャーな言語でこれを備えてるのはC++の他にはDくらいしかないはず
397 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 01:55:42 ] SFINAE(Substitution Failure Is Not An Error) en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
398 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 01:59:04 ] >>396 取り敢えず CL はどっちも出来るな
399 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 02:06:14 ] >>398 良く分からん CLだと引数の型が確定するのは実行時だから、テンプレートみたいなことはやりようが無いんじゃね?
400 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 02:12:17 ] GF じゃダメなん?
401 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 02:17:12 ] GFって総称関数のこと? それならやっぱり実行時ディスパッチだからテンプレートとは比較できないだろ
402 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 04:48:43 ] >>397 Boostじゃ結構使われてるけど英語しか記事無いのか
403 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 08:11:36 ] GFってgeneric functionのことだと思うけど、それだと >>401 の書いてるように、実行時の型に基づくディスパッチだから、 コンパイル時にディスパッチが行われるC++のテンプレートの特殊化 とは全然違うでしょ
404 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 08:21:47 ] 何で同じ事を2度書く?
405 名前:デフォルトの名無しさん mailto:sage [2008/05/23(金) 08:48:42 ] >>403 packageとcompileで頑張れば、 同じようなものを作れないこともないなあ。 おもしろいかもね。SFINAEはCLOSっぽいね。 まあC++だって総称関数族だから当たり前か。
406 名前:デフォルトの名無しさん mailto:sage [2008/06/02(月) 14:56:29 ] patter match で、 let a = "hoge" in match a with a -> "this is hoge" | "hage" -> "this is hage" | _ -> "other" みたいにして、a を "hoge" としてマッチさせることが出来ないのはどうしてなの
407 名前:デフォルトの名無しさん mailto:sage [2008/06/02(月) 15:25:34 ] パタンに変数参照を書けないから。 パタン中に変数書くときは束縛になるじゃん。
408 名前:デフォルトの名無しさん mailto:sage [2008/06/02(月) 15:37:05 ] あ、そうか。束縛と区別できないのか。 ありがとう でもグローバルに識別子を持っているとき 例えば root_user_name = "hoge" とかあるとして 直接 "hoge" はタイプしたくない場合 match user_name with eval(root_user_name) -> "root user" | _ -> "normal user" とか書きたくなるんだよね 単純なときは if else だけど、複雑なときに書きたくなる
409 名前:デフォルトの名無しさん mailto:sage [2008/06/02(月) 19:00:31 ] つ whenキーワード
410 名前:デフォルトの名無しさん [2008/06/02(月) 19:56:37 ] match user_name with | user when user=root_user_name -> "this is root user" | "hage" -> "this is hage" | _ -> "other" で合ってる?
411 名前:デフォルトの名無しさん mailto:sage [2008/06/02(月) 20:30:39 ] つ if
412 名前:デフォルトの名無しさん mailto:sage [2008/06/03(火) 00:08:07 ] >409 ありがとー 知らなかった すげー恥ずかしい
413 名前:デフォルトの名無しさん mailto:sage [2008/06/03(火) 02:56:54 ] >>412 かじりかけじゃしょうがないと思うからがんばれ。
414 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 08:27:09 ] パターンマッチにパターンじゃなくて式を書いちゃうのは初心者にはよくあること。 入門書は振れるべきかもわからんね。
415 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 11:13:11 ] つ 入門OCaml
416 名前:デフォルトの名無しさん mailto:sage [2008/06/05(木) 19:44:14 ] 軸がぶれている
417 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 10:41:42 ] 質問です、リストの文字を全部つなげるとき List.fold_left (^) "" ["1"; "2"; "3"] とか書くとするじゃないですか でも例えばちょこっと関数を間に挟みたいとき、 let conv x = x ^ "!!" in List.fold_left (fun a b -> a ^ (conv b)) "" ["1"; "2"; "3"] とか書くのって違うのかなとか思ってるんですよ (fun a b ->a ^ (conv b)) の部分をもっとこう関数の合成みたいな感じで短く書く方法ってないですかね
418 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:19:57 ] 十分簡潔に書けていると思う。わかりやすいし。 なぜそんなに短さにこだわる?
419 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:31:55 ] 質問の趣旨とずれているが、そもそも (^) を fold するのはお勧めできない。 文字列コピーが多すぎるから。String.concat とか、 Buffer を使うべし。 上の例は、 String.concat "" (List.map conv ["1"; "2"; "3"]) これで十分だろう。(^) を使うなら417で十分。無理に短く書いて喜ぶ言語ではない。
420 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 12:36:50 ] ,,,,,,,,,,,,,,,,,,,,,,,,,, /": : : : : : : : \ /-─-,,,_: : : : : : : : :\ / '''-,,,: : : : : : : :i /、 /: : : : : : : : i ________ r-、 ,,,,,,,,,,、 /: : : : : : : : : :i / L_, , 、 \: : : : : : : : :i / λ抽象したら /●) (●> |: :__,=-、: / < 負けかなと思ってる l イ '- |:/ tbノノ \ l ,`-=-'\ `l ι';/ \ ヽトェ-ェェ-:) -r'  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ヾ=-' / / ____ヽ::::... / ::::| / ̄ ::::::::::::::l `──'''' :::|
421 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 14:08:51 ] >>417 俺だったら先にmapする
422 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 14:42:08 ] 俺はconvを2引数にしてこんな感じにするかな List.fold_left conv "1" ["2"; "3"]
423 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 21:29:56 ] ありがとうございました Buffer は知ってたけど、String.concat は知りませんでした map 先にやって、String.concat で書くことにします
424 名前:デフォルトの名無しさん mailto:sage [2008/06/07(土) 23:34:58 ] OCamlでファイルIOするときUnix.lseekとかが file_descr -> int -> seek_command -> int でintで足りない場合が多々あるかと思うのですが、 皆さんは大きなファイルのIOをするときはどうしてますか? オフセットの計算とかも Int64.add pos (Int64.mul index 4L) みたいにしてやってますか?
425 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 01:20:52 ] Unix.LargeFile おまいら、ライブラリ関数で迷ったらまず .mli 読むか、grep するか、 ocamlbrowser でも使えよな。
426 名前:デフォルトの名無しさん mailto:sage [2008/06/08(日) 01:34:33 ] >>425 おお、ありがとうございます!
427 名前:デフォルトの名無しさん [2008/06/08(日) 17:22:38 ] >>424 31bitがだめなら63bitがあるじゃない。 # 0xffffffff;; - : int = 4294967295
428 名前:デフォルトの名無しさん mailto:sage [2008/06/09(月) 00:54:23 ] >>427 つまらん
429 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 18:32:15 ] 質問。関数型言語の特徴の一つとしてパターンマッチって出てくるけど何が利点なの? ifの構文糖衣のようにも思えるけど
430 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 19:07:00 ] 簡潔に書ける
431 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 19:48:17 ] >>429 もしパターンマッチがないとすれば、代数的データ型から値を取り出したい場合はどうする? たとえばHaskellのMaybe型のJust 3という値から、3という値を取り出したい場合はどうする?
432 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 20:25:17 ] それはアクセス関数が自動生成されるようにすれば済む話じゃないか
433 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 20:39:02 ] >>429 構文糖には何も利点がないとでも?
434 名前:デフォルトの名無しさん [2008/06/12(木) 22:33:33 ] 安全なダウンキャストができることとか?
435 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 22:41:54 ] >>434 x + yって中間記法、よく出てくるけど何が利点なの? (+ x y)の構文糖衣のようにも思えるけど
436 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 22:42:53 ] >>432 具体的に実装するとすればどうしますか? MaybeにはNothingという値もあるんですよ。
437 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 23:11:58 ] >>436 入力が不適なら例外発生
438 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 23:24:50 ] >>437 Maybeは代数的データ型のひとつの定義に過ぎませんよ。 Just aとNothing以外にHogeという値がある別の定義があったらどうするんですか? 定義はいくらでも作れますよ。
439 名前:デフォルトの名無しさん mailto:sage [2008/06/12(木) 23:37:45 ] >>438 言っている意味が分からん アクセサの自動生成はHaskellが既にやってること(フィールドラベル使ったときに)だし、技術的な問題はないと思うんだが
440 名前:デフォルトの名無しさん mailto:sage [2008/06/13(金) 03:16:09 ] パターンマッチの利点: 簡潔 - 記述しやすい (accessors (or deconstructors) for free) 安全 - non exhaustiveness check 速度 - 分岐が集約されているので最適化が楽 (ifの繰り返しを解析するのにくらべて) 以上。他にあるかな? (というか、そもそもパターンマッチは関数型言語の特徴ではありません。 関数型言語が採用しているADTの特徴というべきでしょ。)
441 名前:デフォルトの名無しさん mailto:sage [2008/06/13(金) 03:29:17 ] 問題 パターンマッチを採用している手続き型言語を挙げよ
442 名前:デフォルトの名無しさん mailto:sage [2008/06/13(金) 05:12:14 ] awkはパターンマッチなのかな
443 名前:デフォルトの名無しさん mailto:sage [2008/06/13(金) 08:15:48 ] マセマティカ 項書換えシステム全般 (論理型も含む)
444 名前:デフォルトの名無しさん mailto:sage [2008/06/13(金) 08:24:46 ] Scalaはcase classがある。 パターンマッチ渡しはできないが、match case文がある。 www.scala-lang.org/intro/caseclasses.html Extractorはユーザ定義もできる。 www.scala-lang.org/intro/extractors.html
445 名前:デフォルトの名無しさん mailto:sage [2008/06/15(日) 00:12:39 ] SML#はもう開発止まっちゃったの?
446 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 13:51:28 ] F#(OCAML系)があるしなあ。 JNI(Java Native Interface)の中の人は、 SML/NJのWin32対応をやっていた人だった。 Modular Monadic Semanticsの人。
447 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 17:39:37 ] メンバがわりと沢山ある構造体(record)がいくつか必要な時は皆さん メンバの名前が被らないように注意してレコード作ってますか? それともクラスにしますか?
448 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 21:15:11 ] >>446 何か勘違いしていると思われ
449 名前:デフォルトの名無しさん [2008/06/16(月) 21:15:42 ] F#があるのとSML#関係なくね?SML.NETの存在は微妙かも知れんけど
450 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 21:18:34 ] >>447 モジュール名で区別でおk OCamlでオブジェクトの濫用はお勧めできない
451 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 22:45:23 ] SML#の「#」は、.NETよりも歴史が長い
452 名前:デフォルトの名無しさん mailto:sage [2008/06/16(月) 22:45:43 ] プロジェクト期間終了したから取りあえず一息つきたいんじゃないの? O堀さんのことだからこれで終りとは思えないが。
453 名前:デフォルトの名無しさん mailto:sage [2008/06/17(火) 03:18:35 ] >>450 おお、目から鱗ですありがとう! このスレは勉強になります。。 俺もできるならクラスは使いたくなかったので助かりましたわ。
454 名前:デフォルトの名無しさん [2008/06/22(日) 02:24:57 ] SML♯で,配列 data[](要素数 n)と int型の i,j を引数にとって, 要素 data[i] と data[j] を入れ替えた配列 を出力する関数 ってどうやればいいんかいな?
455 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 22:44:31 ] 宿題ですか?
456 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 23:37:58 ] OCamlのStream便利だな。。。何でもかんでもコレ使いたくなっちゃうわ。 何かマズいことあるのかな?
457 名前:デフォルトの名無しさん [2008/06/23(月) 01:54:09 ] マズいことはないけど破壊的なのがなにかと使いにくいと思う。
458 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 01:56:52 ] >>457 つまりHaskell最高ってことか?
459 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 02:57:29 ] ほとんどのデータがint縛りっていうか、31bit制限があるところがツラいと思うんですが、 色々と工夫というかテクがあるなら教えて頂きたいです。
460 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 06:54:26 ] >>456 人生、これストリームなり
461 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 12:22:57 ] [1;2;3;4]を入力すると[1;3;6;10]を返す関数sigmaを書いたんですが sigma関数の箇所、もっと効率的なやり方があるような気がしてむずがゆい感じがしてます。 何かアドバイスいただけないでしょうか let iota n = List.init n ((+)1) in let sum lst= List.fold_left (+) 0 lst in let rec take n lst = match n with 0 -> [] | 1 -> [List.hd lst] | _ -> (List.hd lst)::take (n-1) (List.tl lst) in let sigma lst = List.rev (List.fold_left (fun x y->sum (take y lst)::x) [] (iota (List.length lst))) in sigma [1;2;3;4;5;6];;
462 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 13:13:09 ] 累積変数で、これまでの和を持ち運ぶ
463 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 14:45:07 ] ありがとう。こんな感じですかね (途中まで同じ) let sigma lst = let accum = ref [] in List.rev (List.fold_left (fun x y-> accum:=y::!accum; sum !accum::x) [] (iota (List.length lst))) in sigma [1;2;3;4;5;6];;
464 名前:デフォルトの名無しさん [2008/06/23(月) 15:38:22 ] えー。「ここまでの結果」を「引数で」持ちまわるんだよ。再帰終了するところでその引数をそのまま返す。
465 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 15:59:00 ] んー、持ち回る引数がfoldの中なので、プログラム全体の形、結構変わりますよね? こういった変換は慣れていないので、ちょっと時間がかかりそうです
466 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 17:53:21 ] iotaとかsumとかtakeとかを使わないで、さらにfoldにこだわらなくて、かつ再帰を使っていいなら こんなのはどうっすかね? let sigma l = let rec sigma' cur r = function | [] -> List.rev r | x::xs -> let next = cur + x in sigma' next (next :: r) xs in sigma' 0 [] l # sigma [];; - : int list = [] # sigma [1;2;3;4;5;6];; - : int list = [1; 3; 6; 10; 15; 21] foldとかを使ったもっとElegante"〜{エレガンテ}〜"な方法を希望ならスマソ。
467 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 20:17:29 ] こんな感じ。 reverse $ snd $ foldl (\(a,xs) b -> let x = a + b in (x,x:xs)) (0,[]) Haskellの構文を使ってるがMLでも同様のはず。
468 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 20:21:41 ] pairにする必要ないんじゃ… tail $ reverse $ foldl (\a b -> (head a + b):a) [0]
469 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 20:37:13 ] >>468 おお、こういうのがノータイムで出てくるようになりたいわ。
470 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 21:44:56 ] let sigma lst = let rec sum lst = match lst with | [] -> [] | car :: cdr -> (List.fold_left (+) 0 lst) :: (sum cdr) in List.rev (sum (List.rev lst));; こんなんどうでっしゃろ?