5

この型を =

type intC = int;;
type boolC = bool;
type stringC = string;;

type component = A of intC | B of boolC | C of stringC;;

コンポーネント A のタイプ a に関数を適用したい場合、コンポーネントを体系的に分解する必要がありますか?

たとえば、私はしなければなりませんか:

let add comp =
  match comp with 
   | A i -> Some (i + 2) (*only A interests me, I return i + 2*)
   | _ -> None           (*otherwise I return nothing*)

次に、コンポーネント A の任意の機能について ? あなたの冗長性を避ける手段はありますか?

4

2 に答える 2

4

型に対して実行する操作の種類によって異なります。

@nlucaroni によって与えられた解決策はまったく問題ありませんが、もう少し一般的な (そして複雑な) ことをしたい場合は、レコードを使用して部分マップ関数を保持できます。

type 'a component_m = {
  a : intC  -> 'a;
  b : boolC -> 'a;
  c : stringC -> 'a;
}

let map_component m = function
  | A a -> m.a a
  | B b -> m.b b
  | C c -> m.c c

let add = map_component {
  a = (fun x -> Some (x + 2)); 
  b = (fun _ -> None);
  c = (fun _ -> None);
}

(fun _ -> None)毎回関数を記述する必要がない場合は、拡張したデフォルト値を使用することもできます。

let none = {
  a = (fun _ -> None);
  b = (fun _ -> None);
  c = (fun _ -> None);
}

let add = map_component { none with a = fun x -> Some (x+2) }

ファンクターでも同じことができますが、私の意見では、これはやり過ぎです。

于 2012-04-26T18:53:25.733 に答える
3

コンポーネントの破棄を行う関数に高次関数を渡すことができます。

let apply_if_a f = function
   | A i          -> Some (f i)
   | (B _ | C _)  -> None

このタイプは、

val apply_if_a : (int -> 'a) -> component -> 'a option

ご覧のとおり、 の任意の値に適用される任意の関数に対してポリモーフィックですA。また、ほとんどの人はキャッチオール、、、を避け、_代わりに網羅的です。

于 2012-04-26T17:46:50.333 に答える