如何在 SML 中将字符串转换为 int(而不是 int 选项)

How to convert String to int(and not to int option) in SML

我正在尝试使用 Int.fromString 函数从字符串中提取整数值 但正如我们所知,它的规格是:String -> int option。所以应用 Int.fromString 的结果是类型 int option。但是我需要 int 类型的结果。我也确信提取的部分是整数。如何做到这一点?

你可以在表达式的左边使用SOME

val SOME x = Int.fromString "3";
val x = 3 : int

您可以使用 valOf 函数获取选项的 SOME 值:

val i : int = valOf (Int.fromString "1")

像@JohnColeman,我不能推荐像

这样的部分函数
fun intFromString s = let val SOME i = Int.fromString s in i end

fun intFromString s = case Int.fromString s of SOME i => i

fun intFromString s = valOf (Int.fromString s)

如果必须的话,至少让错误有意义,这样当你假设的不变量被破坏时你可以很容易地找到它,因为它只是代表程序员的善意维护:

fun intFromString s =
    case Int.fromString s of
         SOME i => i
       | NONE => raise Fail ("Could not convert string '" ^ s ^ "' to int!")

函数 Int.fromString : string -> int option 是安全的,但如果您不喜欢它,您可以这样做:

fun intFromString s default_i =
    Option.getOpt (Int.fromString s, default_i)

val intFromString : string -> int -> int

尽管在调用函数或专门的绑定运算符 (>>=) 中处理 NONE 应该是很自然的。这归结为 API 设计,而不是质疑安全功能与不安全功能。

如果您确定可以从字符串中提取整数,为什么不将这种确定性嵌入到类型中呢?例如。通过将这些字符串包装在抽象数据类型/模块中,只允许从模块内生成这些肯定可转换的字符串。一个最小的实现可能是这样的:

signature INT_STRING =
sig
    type int_string
    val fromInt : int -> int_string
    val toInt : int_string -> int
    val lift : (string -> 'a) -> (int_string -> 'a)
end

structure IntString :> INT_STRING =
struct
    type int_string = string
    fun fromInt i =
        if (i < 0)
        then "-" ^ Int.toString (Int.abs i)
        else Int.toString i

    fun toInt s =
        if String.sub (s, 0) = #"-"
        then ~ (valOf (Int.fromString (String.extract (s, 1, NONE))))
        else valOf (Int.fromString s)

    fun lift f s = f s
end

此时我证明 valOf 的使用是合理的,因为我知道生成 IntString.int_string 类型值的唯一方法是通过 IntString.fromInt。该模块可以像这样使用:

(* This property can be tested for arbitrary inputs i. *)
val id_prop i = IntString.toInt (IntString.fromInt i) = i
val test1 = id_prop 123
val test2 = id_prop ~55
val test3 = id_prop 0

(* Some standard string functions work just as well. *)
val intStringSize = IntString.lift String.size
val intStringPrint = IntString.lift String.print

val test4 = intStringSize (IntString.fromInt 555) = 3
val _ = intStringPrint (IntString.fromInt 12345)