我有一个返回(char * int) list list
的函数,如[[(#"D", 3)], [(#"F", 7)]]
,现在我想知道是否可以将它转换为字符串,以便我可以使用I / O并读取它到另一个文件?
答案 0 :(得分:3)
首先,我假设你的意思是[[(#"D", 3)], [(#"F", 7)]]
(注意额外的parens),因为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 repo(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