1

I'm trying to create a List reading a text file, for example I have a text file like this "1 5 12 9 2 6" and I want to create a list like this [1,5,12,9,2,6] using SML

4

1 回答 1

1

您可以将此任务分为几个子问题:

  1. 将文件读入字符串可以通过

    type filepath = string
    
    (* filepath -> string *)
    fun readFile filePath =
        let val fd = TextIO.openIn filePath
            val s = TextIO.inputAll fd
            val _ = TextIO.closeIn fd
        in s end
    

    图书馆_TextIO

  2. 可以将字符串转换为由空格分隔的字符串列表

    (* string -> string list *)
    fun split s =
        String.tokens Char.isSpace s
    

    功能_String.tokens

  3. 可以将字符串列表转换为整数列表

    (* 'a option list -> 'a list option *)
    fun sequence (SOME x :: rest) = Option.map (fn xs => x :: xs) (sequence rest)
      | sequence (NONE :: _) = NONE
      | sequence [] = SOME []
    
    fun convert ss = sequence (List.map Int.fromString ss)
    

    由于任何一个字符串到整数的转换Int.fromString都可能失败并产生一个NONE,List.map Int.fromString将产生一个“int 选项列表”而不是“int 列表”。这个“int 选项”列表可以转换成一个可选的“int 列表”,即去掉SOME所有“int 选项”中的 ,但如果只有一个NONE,则整个结果被丢弃,变成NONE。这给出了最终类型“int 列表选项”(NONESOME [1,2,...])。

    请参阅对这种递归有用Option.map函数。

  4. 结合这些,

    (* filepath -> int list *)
    fun readIntegers filePath =
        convert (split (readFile filePath))
    

这种方法确实会产生一些可能不需要的行为:

  • 文件系统错误将readIntegers引发Io异常
  • 文件内的字符串~5将被解释为负五
  • 该字符串-5将产生失败 ( NONE)
  • 该字符串123a将产生数字 123 (Int.toString有点太宽容了)

您可能想要解决这些问题。

于 2020-02-10T15:45:02.650 回答