3

次のような Stack の定義の始まりがあるとします。

signature STACK = sig
  type 'a stack
end;

structure Stack :> STACK = struct
  type 'a stack = 'a list
end;

リストをスタックにキャストできないため、明らかにこれは機能しません。

- [5] : int Stack.stack;
stdIn:1.2-1.23 Error: expression doesn't match constraint [tycon mismatch]
  expression: int list
  constraint: int Stack.stack
  in expression:
    5 :: nil: int Stack.stack

つまり、Stack.push または Stack.pop 関数を作成した場合、スタックが必要になるため、int リストを渡すことができませんでした。

実際の質問を定式化するために標準 ML についてもっと知っていればよかったのですが、これが機能しないことはわかっており、署名と構造にアプローチする方法がわかりません。

4

2 に答える 2

5

構造を宣言するときは、不透明なシグネチャ マッチング( :>) を使用しています。

不透明な署名の一致が意味することは、構造内で宣言された型の背後にある基になる型が隠されているということです。

これを望まない場合は、透過的な署名一致( )を使用できます。:

トランスペアレント シグニチャ マッチングの例:

structure Stack : STACK = struct
  type 'a stack = 'a list
end;

これを行う前に、そうしないことの利点を考慮してください。不透明な署名マッチングを使用すると、基礎となる実装が隠されます。基礎となる実装を (たとえば、ツリー構造に) 変更したい場合は、構造の外部では、提供した関数以外の関数を使用できないことを知っていれば、それを行うことができます。

代わりにtoListandfromList関数を提供して変換を実行することもできます。

(* in the signature *)
val toList : 'a stack -> 'a list
val fromList : 'a list -> 'a stack

(* in your structure *)
fun toList s = s
fun fromList s = s

その後、基になる実装を変更する場合、プログラム全体を変更する必要はなく、これら 2 つの関数を変更するだけで済みます。

于 2013-08-25T13:16:53.560 に答える
3

関数toListを作成しfromList、セバスチャンが示唆するように、非常に優れています。pushまたは、直接のインポートとエクスポートを許可せず、popとによる作成のみを許可する、より制限的なインターフェイスを作成できますempty

signature STACK =
sig
  type 'a stack
  val push : 'a -> 'a stack -> 'a stack
  val pop : 'a stack -> ('a * 'a stack)
  val peek : 'a stack -> 'a
  val empty : 'a stack
end

structure LStack :> STACK =
struct
  type 'a stack = 'a list
  fun push = ...
  fun pop = ...
  fun peek = ...
  val empty = []
end
于 2013-08-29T20:03:10.857 に答える