我有一个函数返回像(char * int) list list
这样的[[(#"D", 3)], [(#"F", 7)]]
,现在我想知道是否可以将其转换为字符串,以便我可以使用I/O并将其读取到另一个文件中?
最佳答案
首先,我假设您的意思是像[[(#"D", 3)], [(#"F", 7)]]
这样的值(请注意额外的括号),因为SML需要在元组构造周围加上括号。 OCaml使用略有不同的语法,并且仅允许使用逗号(如a, b
)来构造元组。我之所以这样说,是因为以下内容完全是针对标准ML的,而不适用于OCaml,因为我认为在OCaml中,您最好的选择是完全不同的方法,对此我不太了解(宏,即ocamlp4/5)。因此,我认为这只是一个错字,并且您对Standard ML感兴趣。
现在,不幸的是,标准ML中没有通用的toString
函数。诸如此类的东西在语言和实现方面必须有某种特殊的支持,因为不可能用'a -> string
类型编写函数。基本上,您必须为每种类型toString : t -> string
编写自己的t
。
可以想象,这很快就变得很乏味。我花了一些时间研究选项(针对此选项以及其他样板函数,如compare : 't * 't -> order
),论文“工作中的ML'er的泛型”(http://dl.acm.org/citation.cfm?id=1292547)中概述了一种非常有趣的技术,但它相当先进,我可以从来没有真正获得过要编译的代码(那说该论文非常有趣)。该论文中描述的完整泛型库位于MLton lib存储库(https://github.com/MLton/mltonlib/tree/master/com/ssh/generic/unstable)中。也许您会有更好的运气?
恕我直言,这是一种重量稍轻的方法,虽然功能不强,但更易于理解。在读完该论文并努力使其工作后,我写了这篇文章。这个想法是为toString
函数(在这种情况下称为show
)编写构建块,并将它们与您自己类型的其他函数组成。
structure Show =
struct
(* Show.t is the type of toString functions *)
type 'a t = 'a -> string
val int: int t = Int.toString
val char: char t = Char.toString
val list: 'a t -> 'a list t =
fn show => fn xs => "[" ^ concat (ExtList.interleave (map show xs) ",") ^ "]"
val pair: 'a t * 'b t -> ('a * 'b) t =
fn (showa,showb) => fn (a,b) => "(" ^ showa a ^ "," ^ showb b ^ ")"
(* ... *)
end
由于您的类型实际上没有任何用户定义的数据类型,因此使用此结构编写
toString
函数非常容易:local
open Show
in
val show : (char * int) list list -> string = list (list (pair (char, int)))
end
- show [[(#"D", 3)], [(#"F", 7)]] ;
val it = "[[(D,3)],[(F,7)]]" : string
我喜欢的是,组合函数的读取方式就像翻过来的类型一样。这是一种非常优雅的风格,我不能赞扬它,就像我从上面链接的泛型中获得的那样。
Show
的其余代码(以及用于相等性比较的相关模块Eq
)在此处:https://github.com/spacemanaki/lib.sml