我正在使用 SML/NJ 中包含的 S-Expression 库。在我的用例中,包含 SExpressions 的文件将始终为 String List List List 类型。 SExpParser.parse 成功解析了我的文件。问题是解析器的返回类型是 SExp.value List,其中 value 定义为
datatype value
= SYMBOL of Atom.atom
| BOOL of bool
| INT of IntInf.int
| FLOAT of real
| STRING of string
| QUOTE of value
| LIST of value list
我把数据转换成图表的函数是
fun makeGraph (n:string list list list)
。
现在,问题自然是编译器对我大吼大叫,因为它无法在编译时确定解析器的返回类型实际上是一个字符串列表列表列表。因此,我尝试使用模式匹配来确定类型,但我一直无法编译它(这与 this 想法不符)。
一些我尝试过但没有用的东西:
fun convert (SExp.LIST ((SExp.LIST ((SExp.STRING s)::ss))::ls)) = ArrayGraph.makeGraph ls
| convert _ = raise Fail "convert"
fun convert values:SExp.value =
case values of
SExp.LIST ((SExp.LIST ((SExp.STRING s)::ss))::ls) => ArrayGraph.makeGraph ls
| _ => raise Fail "convert"
fun convert values:SExp.value =
case values of
SExp.LIST(v) => map (fn x => convert x) v
| SExp.STRING(s) => s::nil
| _ => raise Fail "convert"
我真的被这个问题难住了,希望得到任何帮助。我似乎也没有找到任何人使用这个库的例子,所以如果你有任何一个,我将不胜感激。谢谢。
作为参考,这里是 sml/nj s 表达式代码的链接:https://github.com/smlnj/smlnj/blob/main/smlnj-lib/SExp/README
前两个不能工作,因为
ls
是SExp.value list
,而不是string list list
。
第三个不能工作,因为
s::nil
是一个string list
,如果convert x
是一个string list list
,那么map (fn x => convert x) v
是一个string list list list
。
从底部开始,使用琴弦,然后向上遍历每个嵌套列表。
这样的事情应该有效:
fun to_string (SExp.STRING s) = s
| to_string _ = raise Fail "to string"
fun to_string_list (SExp.LIST ss) = map to_string ss
| to_string_list _ = raise Fail "to string list"
fun to_string_list_list (SExp.LIST ss) = map to_string_list ss
| to_string_list_list _ = raise Fail "to string list list"
fun convert sexp = ArrayGraph.makeGraph (to_string_list_list sexp)
在 SML 中,就像在其他类型化的函数式语言中一样,类型是你的朋友,而不是你的敌人。如果他们看起来像你的敌人,你需要花更多的时间来学习这门语言和它的正常用法。如果你熟悉一门语言 A 并开始学习一门语言 B,你最初会尝试用 B 编程,就好像它是 A 一样,你会感到沮丧。
通过在注释中“声明”其类型来记录任何重要函数或其他值的类型是一种很好的做法,如
(* to_string : SExp.value -> string *)
fun to_string (SExp.STRING s) = s
| to_string _ = raise Fail "to string"fun to_str
[此类预先声明应该是语言本身的一部分,并且很可能会出现在 Successor ML 语言中。 ]
有了更多的经验,您将能够在编写或阅读代码时在脑海中键入检查代码,但是这样的注释非常有帮助。当我试图理解别人的 SML 代码时,我首先在每个声明中添加这样的“键入”注释。
如需进一步讨论,请尝试 standardml.zulipchat.com(您需要一个 Zulip 帐户)。