Sml 通过将内置列表类型强制转换为自定义堆栈类型来理解SIG和结构

Sml 通过将内置列表类型强制转换为自定义堆栈类型来理解SIG和结构,sml,smlnj,Sml,Smlnj,假设我有堆栈定义的开头,如下所示: 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 mis

假设我有堆栈定义的开头,如下所示:

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的知识,以制定一个真正的问题,我只是知道这不起作用,我不知道如何处理签名和结构

在声明结构时,使用不透明的签名匹配(
:>

不透明签名匹配的意思是,结构内部声明的任何类型背后的底层类型都是隐藏的

如果不希望出现这种情况,可以使用透明签名匹配(

具有透明签名匹配的示例:

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

<强>在执行此项之前,考虑不这样做的优点:如果使用不透明的签名匹配,则隐藏了基础实现。如果您希望更改底层实现(例如,更改为树结构),您可以在知道结构之外的任何功能都不能使用您提供的功能的情况下进行更改

您可能希望提供
toList
fromList
功能来执行转换:

(* 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

如果您随后更改了底层实现,则只需更改这两个函数,而不必对整个程序进行更改。

按照Sebastian的建议创建函数
toList
fromList
。或者,您可以创建一个更严格的界面,该界面不允许直接导入和导出,只允许通过
推送
弹出
创建:

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