创建一个使用 SML 读取文件的列表
Create a list reading a file with SML
我正在尝试创建一个读取文本文件的列表,例如,我有一个这样的文本文件 "1 5 12 9 2 6"
,我想使用 [=14] 创建一个这样的列表 [1,5,12,9,2,6]
=]SML
你可以把这个任务分成几个子问题:
可以使用
将文件读入字符串
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
可以使用
将字符串转换为由空格分隔的字符串列表
(* string -> string list *)
fun split s =
String.tokens Char.isSpace s
可以使用
将字符串列表转换为整数列表
(* '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 option list" 而不是 "int list". "int option" 列表可以转换为可选的 "int list",即删除所有 "int option" 中的 SOME
,但如果只有一个 NONE
,则整个结果被丢弃并变为 NONE
。这给出了最终类型 "int list option"(NONE
或 SOME [1,2,...]
)。
参见 the Option.map
function 对这种递归很有用。
结合这些,
(* filepath -> int list *)
fun readIntegers filePath =
convert (split (readFile filePath))
这种方法确实会产生一些可能不需要的行为:
- 文件系统错误会使
readIntegers
抛出 Io
异常
- 文件里面的字符串
~5
会被解释为负五
- 字符串
-5
将产生失败(NONE
)
- 字符串
123a
将产生数字 123(Int.toString
有点太宽容了)
您可能想要解决这些问题。
我正在尝试创建一个读取文本文件的列表,例如,我有一个这样的文本文件 "1 5 12 9 2 6"
,我想使用 [=14] 创建一个这样的列表 [1,5,12,9,2,6]
=]SML
你可以把这个任务分成几个子问题:
可以使用
将文件读入字符串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
可以使用
将字符串转换为由空格分隔的字符串列表(* string -> string list *) fun split s = String.tokens Char.isSpace s
可以使用
将字符串列表转换为整数列表(* '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 option list" 而不是 "int list". "int option" 列表可以转换为可选的 "int list",即删除所有 "int option" 中的SOME
,但如果只有一个NONE
,则整个结果被丢弃并变为NONE
。这给出了最终类型 "int list option"(NONE
或SOME [1,2,...]
)。参见 the
Option.map
function 对这种递归很有用。结合这些,
(* filepath -> int list *) fun readIntegers filePath = convert (split (readFile filePath))
这种方法确实会产生一些可能不需要的行为:
- 文件系统错误会使
readIntegers
抛出Io
异常 - 文件里面的字符串
~5
会被解释为负五 - 字符串
-5
将产生失败(NONE
) - 字符串
123a
将产生数字 123(Int.toString
有点太宽容了)
您可能想要解决这些问题。