【发布时间】:2014-03-04 01:36:09
【问题描述】:
我有一个返回(char * int) list list 的函数,例如[[(#"D", 3)], [(#"F", 7)]],现在我想知道是否可以将其转换为字符串,以便我可以使用I/O 并将其读入另一个文件?
【问题讨论】:
标签: type-conversion sml
我有一个返回(char * int) list list 的函数,例如[[(#"D", 3)], [(#"F", 7)]],现在我想知道是否可以将其转换为字符串,以便我可以使用I/O 并将其读入另一个文件?
【问题讨论】:
标签: type-conversion sml
首先,我假设您的意思是像[[(#"D", 3)], [(#"F", 7)]] 这样的值(注意额外的括号),因为 SML 需要围绕元组构造的括号。 OCaml 使用稍微不同的语法,并且只允许使用逗号(如a, b)来构造元组。我提到这一点是因为下面的内容完全特定于标准 ML,并且不适用于 OCaml,因为我相信在 OCaml 中你最好的选择是一种完全不同的方法,我不太了解(宏,即 ocamlp4/ 5)。所以我认为这只是一个错字,并且您对标准 ML 感兴趣。
现在,不幸的是,标准 ML 中没有通用的 toString 函数。像这样的东西必须在语言和实现上有某种特殊的支持,因为不可能用'a -> string 类型编写函数。您基本上必须为每种类型 t 编写自己的 toString : t -> string。
您可以想象,这很快就会变得乏味。我花了一点时间研究这些选项(对于这个和其他样板函数,如 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
【讨论】:
ExtList 结构到底有什么作用,为什么showstucture 需要它?
ExtList 只是一些用于操作列表的实用函数:github.com/spacemanaki/lib.sml/blob/master/lib.sml#L3。 Show 模块在Show.list 中使用interleave。
__str__ 和 __repr__ 机制)相比,它仍然需要大量工作。