dポイントプレゼントキャンペーン実施中!

StandardMLで整数リストの奇数・偶数番目の要素の和を組として返す関数sumを作りたい。
sum:int list->int*int。sum([1,2,3,4])ならば(4,6)となるような関数。

自分で途中までは考えてみました。
fun sum(nil)=nil
| sum(x::xs::xxs)=

どのように条件分岐などをすればよいかが分かりません。
ご指導よろしくお願いします。

A 回答 (5件)

>fun sum(nil)=(0,0)


> | sum(x::y::z)=
現在の関数は、リストの長さが偶数の場合しかマッチしないものとなっています。
『sum (x::nil)』のパターンを追加すれば良いと思います。

この回答への補足

度々すいません。パターンの追加は分かりましたが、このパターンの時にどういった処理をさせればいいでしょうか。下記のプログラムでコンパイルするとエラーメッセージが出ました。

- fun sum(nil)=(0,0)
= | sum(x::nil)=(x+L,M)
= |sum(x::y::z)=
= let
= val(L,M)=sum(z)
= in
= (x+L,y+M)
= end;
stdIn:63.20 Error: unbound variable or constructor: M
stdIn:63.18 Error: unbound variable or constructor: L

補足日時:2009/02/14 18:42
    • good
    • 0
この回答へのお礼

いろいろと教えて頂きありがとうございました。
なんとか自分でプログラムを完成させることができました。

お礼日時:2009/02/14 21:34

というか,これの一個前の質問で出てる


リストを順番に二つに分ける関数があれば
それで終わりじゃないの?

情報系の大学の宿題かレポートっぽいので
あえてMLではなくってHaskell風に書くけど
comp::[Int]->([Int],[Int])

sumtuple::([Int],[Int])->(Int,Int)
sumtuple (xs,ys) = (sum xs, sum ys)
を関数合成した
(sumtuple . comp)::[Int]->(Int,Int)
が求める関数じゃないの?
    • good
    • 0

if~then~elseでは、thenの処理の値の型とelseの後の処理の値の型が一致しなければなりません。



> if L=nil then nil
> else hd(L)+skip(tl(L))

上記の部分を見るとthenの場合の型はリスト型で、elseの場合の型は『+』演算子が
扱える型(intやreal)になると思います。then部とelse部で型が一致していません。
また、作成する関数の返す値の型は『int * int』なのでどちらとも型が合いません。

奇数番目の値を加算する関数をsum、偶数番目の値を加算する関数をskipとすると
以下のようなると考えればよいと思います。
 ・sumとskipを相互再起で定義する
 ・sum、skipとも空のリストの場合は(奇数和初期値,偶数和初期値)として(0,0)を返す
 ・sumの空リスト以外の場合は、skipを先頭要素を除いたリストで呼び出し、
  結果のペアの値の奇数和にリスト先頭要素を加算したペアを作成する
 ・skipはsumと対象な処理とする

関数の大枠は以下のようになると思います。

fun sum nil = (0,0)
| sum (x::xs) = 奇数和を加算する処理
and skip nil = (0,0)
| skip (x::xs) = 偶数和を加算する処理

この回答への補足

何度も質問してすいません。教えて頂いた説明を読みながらいろいろと手を加えてみました。前回作成したものと違っていますが、コンパイルしたときに下記のようなメッセージが出ます。

- fun sum(nil)=(0,0)
= | sum(x::y::z)=
= let
= val(L,M)=sum(z)
= in
= (x+L,y+M)
= end;
stdIn:58.5-64.4 Warning: match nonexhaustive
nil => ...
x :: y :: z => ...

val sum = fn : int list -> int * int

どこを修正すればメッセージが消えて正常に動作するようになるでしょうか。教えてください。

補足日時:2009/02/14 15:23
    • good
    • 0

#1のものです。

#1の回答の関数が分かりにくかったと思うので別の関数を考えました。
やはりsumから呼び出す関数です。
仮にこの関数をsum2とすると『fun sum x = sum2 true (0, 0) x』となります。

○引数
 関数の型は『bool -> int * int -> int list -> int * int』となる。
 引数1:リストの先頭の値が奇数番目かを表すフラグ
 引数2:奇数番目の和と偶数番目の和のペア
 引数3:処理対象となるリスト

○リストがnilの場合の処理
 引数2の値をそのまま返す。

○リストがnil以外の場合の処理
 関数を再帰的に呼び出す。関数に渡す値は以下のように求める。
 関数に渡す引数1:関数で受け取った引数1のフラグの値を反転(notを使用)した値
 関数に渡す引数2:関数で受け取った引数1のフラグの値を条件として処理を分岐
          奇数番目の場合⇒「奇数番目の和+リスト先頭の値」と「偶数番目の和」のペア
          偶数番目の場合⇒「奇数番目の和」と「偶数番目の和+リスト先頭の値」のペア
 関数に渡す引数3:先頭の要素を取り除いたリスト

この回答への補足

度々ありがとうございます。

プログラムを修正してみましたが、コンパイルできません。どこを修正すればいいか教えてください。よろしくお願いします。

修正したプログラム
- fun sum(L)=
= if L=nil then nil
= else hd(L)+skip(tl(L))
= and
= skip(L)=
= if L=nil then nil
= else take(tl(L));

補足日時:2009/02/14 12:06
    • good
    • 0

sumから呼び出す関数として以下のようなものを作成すれば良いと思います。



・odd リスト 奇数番目の和 偶数番目の和
  リストの先頭の値を奇数番目の和に加えevenを呼び出す。
  リストの末尾でペアを返す。
・even リスト 奇数番目の和 偶数番目の和
  リストの先頭の値を偶数番目の和に加えoddを呼び出す。
  リストの末尾でペアを返す。

このような関数を用意し、"odd リスト 0 0"として呼び出します。

odd関数とeven関数は相互に呼び出しているので、andを使って定義する必要があります。以下のような感じです。

fun odd l a b = ・・・
and even l a b = ・・・

この回答への補足

回答して頂きありがとうございます。

MLの勉強を始めたばかりで説明されている内容は分かるのですが、具体的にプログラミングすることができません。
申し訳ありませんが、具体的にプログラムしたものを教えていただけないでしょうか。

補足日時:2009/02/13 23:29
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!