如何在 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)
我正在尝试使用 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)