我正在尝试实现一个测试功能,以比较和显示错误消息(如果它们不相等):

exception AssertionErrorException of string

fun assert(testName, actual, expect) : bool =
    if actual = expect
    then true
    else raise (AssertionErrorException (testName ^ " failed. actual: " ^ actual
                ^ ", expect: " ^ expect ));

不幸的是,如果我使用非字符串参数调用它,它将不起作用:
assert("test1", SOME [], NONE);

无法编译,错误消息为:
Error: operator and operand don't agree [tycon mismatch]
  operator domain: string * string * string
  operand:         string * 'Z list option * 'Y option
  in expression:
    assert ("test1",SOME nil,NONE)

如何解决?

最佳答案

在Haskell中,您将使类型成为Show类型类的实例,并实现show :: Show a => a -> String函数的重载变体,然后打印show x而不是x。不幸的是,这样的类型类在Standard ML中不存在,因此您不得不为要打印的每种数据类型编写自己的show的非重载变体。

一些SML编译器(至少是Moscow ML)支持重载函数makestring,该函数仅适用于内置类型的子集,不适用于任何复合类型。例如。 makestring 2makestring 2.0都可以,但是makestring (0,0)无效。 (编辑:David Matthews在下面的答案中指出,PolyML中的makestring更好。)

如果希望创建一个通用的断言函数来漂亮地打印错误,则可以做的一件事就是为要断言其值的每种类型创建一个带有构造函数的数据类型。这将类似于C中的“联合”类型。

exception AssertionError of string
datatype assert = AssertInt of int
                | AssertReal of real
                | AssertBoolBool of bool * bool
                | ...

fun assertPP (AssertInt i) = Int.toString i
  | assertPP (AssertReal r) = Real.toString r
  | assertPP (AssertBoolBool (b1,b2)) =
    String.concat ["(", Bool.toString b1, ", ", Bool.toString b2, ")" ]
  | assertPP (...) = ...

fun assert (testName, actual: assert, expect: assert) =
    actual = expect  (* ML infers equality for constructors *)
    orelse raise AssertionError (String.concat
        [ testName, " failed. actual: ", assertPP actual,
          ", expect: ", assertPP expect, "." ])

这是一个穷人的替代重载。

关于sml - 如何在SML中将任何内容转换为字符串?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19343731/

10-15 02:26