プログラミング言語 Standard ML 入門 (問題の解答例)
6 リスト

6.4 リスト処理の基本関数

問 6.4

nullhdtl の各関数をパタンマッチングを使って定義せよ.

解答例 

   fun null nil = true
     | null (h::_) = false

   fun hd (h::_) = h

   fun tl (_::t) = t
問 6.5

@revmap の各関数をパタンマッチングを使わずに定義せよ.

解答例 

   fun op @ (L1,L2) = if null L1 then L2 else hd L1 :: (tl L1 @ L2)

   fun rev L = if null L then nil else rev (tl L) @ [hd L]

   fun map f L = if null L then nil else f (hd L) :: map f (tl L)
問 6.6

以下のリスト処理関数を定義せよ.

  1. 1.

    整数のリストの総和を求める関数 sumList

  2. 2.

    要素がリストに存在するか否かを判定する関数 member

  3. 3.

    リスト中の重複する要素を取り除く関数 unique

  4. 4.

    ’a -> bool 型の関数P’a list 型のリストLを受け取り, リストLから関数Ptrue を返す要素のみを取り出す関数 filter

  5. 5.

    リストのリストを1つのリストにする関数 flatten. たとえば,
    - flatten [[1],[1,2],[1,2,3]]; val it = [1,1,2,1,2,3] : int list のような動作をする.

  6. 6.

    文字列のリストと文字列の組を受け取り,各リストの要素を文字列でつないだ文字 列を返す関数 splice. たとえば,
    - splice (["","home","ohori","papers","mltext"],"/"); val it = ”/home/ohori/papers/mltext” : string のような動作をする.

解答例 

   fun sumList nil = 0
     | sumList (h::t) = h + sumList t

   fun member a nil = false
     | member a (h::tl) = a = h orelse member a tl

   fun unique nil = nil
     | unique (h::tl) =
       let
         val tl’ = unique tl
       in
         if member h tl’ then tl’ else h::tl’
       end

   fun filter P nil = nil
     | filter P (h::tl) =
       if P h then h :: filter P tl else filter P tl

   fun flatten nil = nil
     | flatten (h::tl) = h @ flatten tl

   fun splice (nil,_) = ""
     | splice ([x],_) = x
     | splice ((h::t),s) = h ^ s ^ splice (t,s);
問 6.7

以下のリスト処理関数を定義せよ.

  1. 1.

    与えられたリストの先頭から始まるすべての部分リストを返す関数 prefixListおよび 最後までのすべての部分リストを返す関数 suffixList. たとえば
    - prefixList [1,2,3]; val it = [[1],[1,2],[1,2,3]]: int list list - suffixList [1,2,3]; val it = [[1,2,3],[2,3],[3],[]]: int list list  
    のような動作をする.

  2. 2.

    与えられたリストの中のすべての部分リストを返す関数 allIntervals. たとえば,
    - allIntervals [1,2,3]; val it = [[1],[1,2],[1,2,3],[2],[2,3],[3]] : int list list  
    のような動作をする. (ヒント: suffixListprefixListmapflatten を組み合わせることを考えよ.)

  3. 3.

    与えられたリストを集合とみなし,そのすべての部分集合を返す関数 powerSet. ただし,与えられたリストは重複を含まないと仮定してよい.

  4. 4.

    与えられたリストを集合とみなし,その中から与えられた数の要素 を取り出して作られるすべての順列をリストとして返す関数 allPermutations. たとえば
    - allPermutations [1,2,3] 2; val it = [[1,2],[2,1],[1,3],[3,1],[2,3],[3,2]]: int list list  
    のような動作をする.(ヒント:flattenpowerSetpermutations を組み合わせることを考えよ.)

解答例 

   fun prefixList nil = nil
     | prefixList (h::tl) =
       let
         val L = prefixList tl
       in
          [h] :: map (fn y => h::y) L
       end

   fun suffixList nil = [[]]
     | suffixList (h::t) =
       let
          val L = suffixList t
       in
          (h::t)::L
       end;

   fun allIntervals L = flatten (map prefixList (suffixList L))

   fun powerSet nil = [nil]
     | powerSet (h::t) =
       let
          val PT = powerSet t
       in
          map (fn x => h::x) PT @ PT
       end

   fun permutations L =
       let fun insertAll s nil = [[s]]
             | insertAll s (h::t) =
                 let val L = insertAll s t
                 in (s::(h::t)) :: (map (fn x => h::x) L)
                 end
       in foldr (fn (x,y) => foldr (fn (a,b) => insertAll x a @ b) nil y)
                [nil]
                L
       end;

   fun allPermutations L n =
       let val subs = filter (fn x => length x = n) (powerSet L)
       in flatten (map  permutations subs)
       end;