How to cast value in SML? Trying to take return type of S-Expression parser and convert to data structure

huangapple go评论52阅读模式
英文:

How to cast value in SML? Trying to take return type of S-Expression parser and convert to data structure

问题

我正在使用SML/NJ中包含的S-Expression库。在我的用例中,包含S-Expressions的文件将始终是类型为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)

现在,问题是,编译器自然会抱怨,因为它无法在编译时确定解析器的返回类型实际上会是一个string list list list。因此,我尝试使用模式匹配来确定类型,但一直无法使其编译通过(基于这个想法)。

我尝试过的一些方法包括:

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-Expression代码的链接:https://github.com/smlnj/smlnj/blob/main/smlnj-lib/SExp/README

英文:

I am using the S-Expression library included in SML/NJ. In my use case, my file containing the SExpressions will always be of type String List List List. The SExpParser.parse successfully parses my file. The problem is the return type of the parser is SExp.value List, where value is defined as

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

My function to convert the data into a graph is fun makeGraph (n:string list list list).
Now, the problem is, naturally, the compiler yells at me because it cannot determine at compile time that the return type of the parser will actually be a string list list list. So, I have tried using pattern matching to determine the type, but I keep failing to get it to compile (something off of this idea).

Some things I have tried that have not worked:

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"

I am really stumped on this problem and would appreciate any help. I also do not seem to find any examples of people using this library, so if you have any of those, I would appreciate a link. Thanks.

For reference, here is a link to the sml/nj s-expression code: https://github.com/smlnj/smlnj/blob/main/smlnj-lib/SExp/README

答案1

得分: 1

第一和第二种方法不适用,因为 lsSExp.value list,而不是 string list list

第三种方法不适用,因为 s::nilstring list,如果 convert xstring 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)
英文:

The first two can't work because ls is a SExp.value list, not a string list list.

The third can't work because s::nil is a string list, and if convert x is a string list list, then map (fn x => convert x) v is a string list list list.

Start at the bottom, with the strings, and work your way upwards over each nesting list.

Something like this should work:


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)

答案2

得分: 1

在SML中,与其他类型化的函数式编程语言一样,类型是你的朋友,而不是你的敌人。如果它们看起来像你的敌人,那么你需要花更多时间学习这门语言及其正常的用法。如果你熟悉语言A,并开始学习语言B,最初你会尝试像在A中编程一样在B中编程,这会让你感到沮丧。

良好的做法是通过在注释中“声明”函数或其他重要值的类型来记录它们的类型,例如:

(* to_string : SExp.value -> string *)
fun to_string (SExp.STRING s) = s
  | to_string _ = raise Fail "to string"fun to_str

[这种预声明应该成为语言本身的一部分,在Successor ML语言中很可能会有。
<标准ML设计者>]

随着经验的积累,你将能够在编写或阅读代码时进行心理类型检查,但这些注释非常有帮助。当我试图理解别人的SML代码时,我会从每个声明处添加这样一个“类型”注释。

有关进一步讨论,请访问standardml.zulipchat.com(你需要一个Zulip账户)。

英文:

In SML, as in other typed functional languages, the types are your friend, not your enemy. If they seem like your enemy, you'll need to spend some more time learning the language and its normal usage. If you are familiar with a language A and you start to learn a language B, you will initially try to program in B as though it is A, and you will be frustrated.

It is good practice to document the type of any significant function or other value by "declaring" its type in a comment, as in

(* to_string : SExp.value -&gt; string *)
fun to_string (SExp.STRING s) = s
  | to_string _ = raise Fail &quot;to string&quot;fun to_str

[Such predeclarations ought to be part of the language itself, and likely will be in the Successor ML language.
<a Standard ML designer>]

With more experience, you will be able to mentally type check your code as you write or read it, but such comments are very helpful. When I am trying to understand someone else's SML code, I start by adding such a "typing" comment at each declaration.

For further discussion, try standardml.zulipchat.com (you will need a Zulip account).

huangapple
  • 本文由 发表于 2023年3月1日 12:50:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75599681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定